fix(usage): treat 402 from the usage-report endpoint as non-retryable#175
fix(usage): treat 402 from the usage-report endpoint as non-retryable#175khaledosman wants to merge 2 commits into
Conversation
A 402 (payment required / insufficient balance) returned by the platform's /gateway/usage endpoint is a permanent rejection: an overdrawn or missing org wallet won't recover within the retry window, so retrying only hammers the platform. Add 402 to _USAGE_NON_RETRYABLE_STATUS_CODES alongside 401/404/409/422. This is behavior-preserving today (402 is already excluded by the >= 500 retry predicate), but makes the intent explicit and keeps the usage reporter robust to future changes in that predicate. Add a unit test asserting a single POST with no retry on 402. Created with Claude Code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 46 minutes and 56 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
WalkthroughHTTP 402 is added to Changes402 Non-Retry Policy and Test Coverage
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~5 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/gateway/api/routes/_platform.py (1)
586-591: ⚡ Quick winDocstring should explicitly include payment-required as non-retryable.
_USAGE_NON_RETRYABLE_STATUS_CODESnow includes402, but the_report_platform_usagedocstring still documents only auth/not-found/conflict/unprocessable. Aligning this text avoids future drift and makes intent clearer for maintainers.Suggested docstring tweak
- impact the user's response path. Non-retryable status codes (auth / - not-found / conflict / unprocessable) short-circuit the retry loop. + impact the user's response path. Non-retryable status codes (auth / + payment-required / not-found / conflict / unprocessable) short-circuit + the retry loop.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/gateway/api/routes/_platform.py` around lines 586 - 591, Update the docstring for the `_report_platform_usage` function to explicitly include "payment-required" (402 status code) in the list of non-retryable status codes. The docstring currently lists only auth/not-found/conflict/unprocessable as non-retryable, but the `_USAGE_NON_RETRYABLE_STATUS_CODES` constant now includes 402. Modify the docstring text to add payment-required to this list so that the documentation accurately reflects the actual implementation.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@src/gateway/api/routes/_platform.py`:
- Around line 586-591: Update the docstring for the `_report_platform_usage`
function to explicitly include "payment-required" (402 status code) in the list
of non-retryable status codes. The docstring currently lists only
auth/not-found/conflict/unprocessable as non-retryable, but the
`_USAGE_NON_RETRYABLE_STATUS_CODES` constant now includes 402. Modify the
docstring text to add payment-required to this list so that the documentation
accurately reflects the actual implementation.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bd438e07-05ea-4ef7-809b-720abc6e678f
📒 Files selected for processing (2)
src/gateway/api/routes/_platform.pytests/unit/test_run_platform_attempts.py
There was a problem hiding this comment.
Pull request overview
This PR makes the platform usage reporter explicitly treat HTTP 402 Payment Required responses from the platform /gateway/usage endpoint as non-retryable, and adds a unit test to pin the intended behavior.
Changes:
- Add
402to_USAGE_NON_RETRYABLE_STATUS_CODESinsrc/gateway/api/routes/_platform.py. - Add a unit test asserting that a
402response results in a single POST attempt (no retries / no backoff sleep).
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
src/gateway/api/routes/_platform.py |
Expands the documented non-retryable status-code set for usage reporting to include 402. |
tests/unit/test_run_platform_attempts.py |
Adds a unit test around _report_platform_usage behavior for 402 responses. |
…2 in test Address review feedback on the usage-report 402 change: - Update the _report_platform_usage docstring to list payment-required among the non-retryable status codes, matching _USAGE_NON_RETRYABLE_STATUS_CODES. - Assert 402 is in the non-retryable set so the unit test guards the classification itself, not just the (currently equivalent) >= 500 retry behaviour. Created with Claude Code. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Description
Add
402to_USAGE_NON_RETRYABLE_STATUS_CODESin_platform.py(now{401, 402, 404, 409, 422}), plus a unit test asserting the usage reporter POSTs once and gives up on a402.A
402(payment required / insufficient balance) returned by the platform's/gateway/usageendpoint is a permanent rejection: the org wallet is overdrawn or missing and won't recover within the retry window, so retrying only hammers the platform. It belongs alongside the other permanent-rejection codes (401/404/409/422) the reporter already short-circuits on.This is behavior-preserving today —
402is already excluded from retry by theshould_retry = response.status_code >= 500predicate in_report_platform_usage, so it isn't retried even now. The change makes the intent explicit in the documented set and keeps the usage reporter robust if that>= 500predicate is ever changed to retry 4xx.Companion to a platform-side fix where an over-budget managed completion now settles the already-incurred charge (driving the org wallet to zero/negative) instead of dropping it, so
/gateway/usagereturns204for that request rather than402. This PR hardens handling of the remaining402cases (e.g. a missing wallet) on the usage-report path. Distinct from #173, which makes404/405/409/410retryable on the provider-fallback path (_FALLBACK_RETRYABLE_STATUS_CODES) — different set, non-overlapping hunks.PR Type
Relevant issues
No otari-side issue. Companion to platform-side fix mozilla-ai/any-llm-platform#1105.
Checklist
tests/unit,tests/integration).ruff check,mypyon the changed files, andpytest tests/unit/test_run_platform_attempts.py). I did not run the full integration suite.AI Usage
AI Model/Tool used: Claude Code (Claude Opus 4.8)
Any additional AI details you'd like to share: Authored as a companion to the platform-side billing fix referenced above.