langchain-ai / langchain-ai/langgraph

Bug: default_retry_on retries non-retryable requests 4xx responses (Response.__bool__ truthiness)

Open
#8,907 1 comment 0 reactions 0 assignees View on GitHub
external
Dominant language
Python
Stars
41.9k
Forks
7.1k
Avg merge
23h 7m
Merged PRs (30d)
30

Description

### Checked other resources

- [x] I searched the current issues and GitHub discussions to avoid duplicates.

### Description

`default_retry_on` in `langgraph/_internal/_retry.py` checks an HTTP error's response for truthiness before inspecting its status code:

```python
if isinstance(exc, requests.HTTPError):
return 500 <= exc.response.status_code < 600 if exc.response else True
```

`requests.Response.__bool__` is defined as `return self.ok`, i.e. `status_code < 400`. So a `Response` carrying any 4xx status is falsy and the whole expression falls back to `True` — every 4xx error raised through `requests` (400, 401, 403, 404, 422, ...) is classified as retryable. The `httpx` branch three lines above only retries 5xx, so the two HTTP stacks behave inconsistently and non-retryable client errors get retried up to the configured limit.

### Example

```python
import requests
from requests import HTTPError
from langgraph._internal._retry import default_retry_on

resp = requests.Response()
resp.status_code = 400
resp.request = requests.Request("GET", "https://example.com").prepare()
exc = HTTPError("400 Client Error", response=resp)

print(bool(resp)) # False — a 400 response is falsy
print(default_retry_on(exc)) # True — LangGraph will retry it
```

The second line should print `False`.

### Solution

Compare `exc.response is not None` instead of relying on truthiness, so a 4xx `HTTPError` falls through the same `500 <= status < 600` check used for `httpx`. I have a one-line fix plus a regression test ready and will open a PR referencing this issue.

Contributor guide

Open the contributing guide

Research direction

Start in langgraph/_internal/_retry.py at default_retry_on and run the requests example from the issue to reproduce the incorrect classification. Add or inspect the mentioned regression test, then verify that 4xx requests errors are not retried while 5xx errors remain retryable and match the httpx branch.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
backend
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.