-
Notifications
You must be signed in to change notification settings - Fork 1
🛡️ Sentinel: Stop retrying on 4xx client errors #188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -600,6 +600,14 @@ | |||||||||||||||||||||||||||
| response.raise_for_status() | ||||||||||||||||||||||||||||
| return response | ||||||||||||||||||||||||||||
| except (httpx.HTTPError, httpx.TimeoutException) as e: | ||||||||||||||||||||||||||||
| # Security: Don't retry on client errors (4xx) unless it's rate limiting (429) | ||||||||||||||||||||||||||||
| if isinstance(e, httpx.HTTPStatusError): | ||||||||||||||||||||||||||||
| status = e.response.status_code | ||||||||||||||||||||||||||||
| if 400 <= status < 500 and status != 429: | ||||||||||||||||||||||||||||
| if hasattr(e, "response") and e.response is not None: | ||||||||||||||||||||||||||||
| log.debug(f"Response content: {sanitize_for_log(e.response.text)}") | ||||||||||||||||||||||||||||
|
Comment on lines
+605
to
+608
|
||||||||||||||||||||||||||||
| status = e.response.status_code | |
| if 400 <= status < 500 and status != 429: | |
| if hasattr(e, "response") and e.response is not None: | |
| log.debug(f"Response content: {sanitize_for_log(e.response.text)}") | |
| # Use getattr to avoid AttributeError if a HTTPStatusError ever lacks a response | |
| response_obj = getattr(e, "response", None) | |
| status = response_obj.status_code if response_obj is not None else None | |
| if status is not None and 400 <= status < 500 and status != 429: | |
| if response_obj is not None: | |
| log.debug( | |
| f"Response content: {sanitize_for_log(response_obj.text)}" | |
| ) | |
| # Don't retry non-rate-limited client errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check for e.response is redundant. The isinstance(e, httpx.HTTPStatusError) check on line 604 already guarantees that e.response exists and is not None. You can simplify this block by removing the conditional check around the logging statement.
| if hasattr(e, "response") and e.response is not None: | |
| log.debug(f"Response content: {sanitize_for_log(e.response.text)}") | |
| raise | |
| log.debug(f"Response content: {sanitize_for_log(e.response.text)}") | |
| raise |
Copilot
AI
Feb 11, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change introduces new retry behavior (do not retry 4xx except 429), but there doesn't appear to be a test asserting the retry count/behavior for (a) a non-429 4xx (should call the request func once) and (b) 429 (should still retry). Adding focused unit tests around _retry_request for these status codes will prevent regressions.
Check warning
Code scanning / Prospector (reported by Codacy)
Use lazy % formatting in logging functions (logging-fstring-interpolation) Warning
Check notice
Code scanning / Pylintpython3 (reported by Codacy)
Use lazy % formatting in logging functions Note