Skip to content

fix(providers): classify Cloudflare neuron 429 as quota_exhausted (#6980) - #7165

Closed
xier2012 wants to merge 4 commits into
diegosouzapw:release/v3.8.49from
xier2012:fix/6980-cloudflare-neuron-quota
Closed

xier2012 wants to merge 4 commits into
diegosouzapw:release/v3.8.49from
xier2012:fix/6980-cloudflare-neuron-quota

Conversation

@xier2012

Copy link
Copy Markdown
Contributor

Summary

Cloudflare Workers AI free-tier exhaustion (429, body: "you have used up your daily free allocation of 10,000 neurons", workers-ai error 4006) was misclassified as a transient rate_limit, so the connection was only locked for ~5s and the combo kept retrying every model against a budget that only resets at UTC midnight.

This PR:

  • Adds a cloudflare-ai provider rule in open-sse/config/providerErrorRules.ts scoped connection (per-account budget, same reasoning as the existing opencode rules) that returns quota_exhausted on a 429 whose body mentions "daily free allocation".
  • Adds /daily free allocation/i to QUOTA_PATTERNS in src/shared/utils/classify429.ts as defense-in-depth for the classify429FromError path.

Test plan

  • New regression test tests/unit/cloudflare-ai-neuron-quota-6980.test.ts (node:test) asserts: the rule matches and yields quota_exhausted/connection, a generic rate-limit 429 does not match, and classify429 classifies the Cloudflare body as quota_exhausted.

Closes #6980

@xier2012
xier2012 requested a review from diegosouzapw as a code owner July 14, 2026 15:24

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces error classification rules and defense-in-depth patterns to correctly identify Cloudflare Workers AI free tier neuron allocation exhaustion (429 errors) as a connection-scoped quota exhaustion rather than a transient rate limit. It also includes corresponding unit tests. The reviewer suggested replacing the top-level dynamic await import statements in the test file with standard static imports for cleaner and more idiomatic TypeScript code.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +8 to +11
const { getProviderErrorRuleMatch } = await import(
"../../open-sse/config/providerErrorRules.ts"
);
const { classify429 } = await import("../../src/shared/utils/classify429.ts");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using top-level dynamic await import is unnecessary here and can be replaced with standard static import statements. Static imports are statically analyzable, cleaner, and more idiomatic in TypeScript.

import { getProviderErrorRuleMatch } from "../../open-sse/config/providerErrorRules.ts";
import { classify429 } from "../../src/shared/utils/classify429.ts";

@diegosouzapw

Copy link
Copy Markdown
Owner

Thank you for tracking down and fixing this — the root cause diagnosis (daily free allocation body falling through QUOTA_PATTERNS) and the fix itself are correct and match what we're merging. Two other contributors (rafaumeu #6983, maxmad64bis #6981) submitted essentially the same fix around the same time; we're merging #6983 because its test suite is broader (11 assertions covering both the provider-rule and classify429 layers, plus edge cases like case-insensitivity and the JSON vs plain-string body shapes). Closing this one as superseded, with full credit for independently catching and fixing #6980 — appreciate you filing it.

@diegosouzapw
diegosouzapw changed the base branch from main to release/v3.8.49 July 15, 2026 08:19
@diegosouzapw

Copy link
Copy Markdown
Owner

Thanks @xier2012! The Cloudflare neuron-429 quota-exhausted classification landed today via #6983, covering this path. Closing as superseded — your analysis of the 429 shape matched what shipped. If you find an uncovered variant, please reopen with the specific response body.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(providers): cloudflare-ai daily neuron exhaustion misclassified as transient rate_limit

2 participants