cloudflare / cloudflare/ai

workers-ai-provider: Workers AI rate-limit error 3021 is classified as non-retryable

Open Beginner friendly
#657 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
TypeScript
Stars
1.2k
Forks
345
Avg merge
13h 31m
Merged PRs (30d)
1

Description

# Workers AI binding error 3021 is treated as non-retryable despite HTTP 429

`workers-ai-provider@4.0.0` does not recognize Workers AI inference RPM-limit code `3021`. The native binding throws `Error("3021: rate limiting: inference request per min rate reached")`. `normalizeBindingError` constructs an `APICallError` without `statusCode`, with `isRetryable: false`, so native AI SDK retries stop immediately.

The corresponding stored Workers AI Gateway response was HTTP 429 with `httpCode: 429`, `internalCode: 3021`, `name: "AiError"`, and the same description. No customer identifiers or private prompts are included here.

## Reproduction

```js
import { createWorkersAI } from "workers-ai-provider";

const model = createWorkersAI({
binding: {
run: async () => {
throw new Error("3021: rate limiting: inference request per min rate reached");
},
},
})("@cf/zai-org/glm-5.3-flash");

try {
await model.doStream({
prompt: [{ role: "user", content: [{ type: "text", text: "Welcome" }] }],
});
} catch (error) {
console.log(error.statusCode, error.isRetryable);
// Actual: undefined, false. Expected: 429, true.
}
```

## Proposed correction

Add `3021: 429` to `WORKERS_AI_ERROR_CODE_TO_STATUS` in `packages/gateway-core/src/workers-ai-errors.ts`. This also lets the existing parser recognize the error code. No custom retry loop is required.

## Validation

An isolated copy of the released package fails four rate-limit tests before the correction and passes all seven tests after it:

- Streaming and non-streaming binding errors retain their cause and map to retryable HTTP 429.
- Native AI SDK `streamText` and `generateText` each recover after two simulated 3021 errors, using the SDK's existing increasing delays (approximately 2 and 4 seconds).
- Invalid input, unknown errors, and cancellation do not retry.

This is controlled local validation, not a production load test. The numeric model/account RPM limit is not established by this report.

Contributor guide

Open the contributing guide

Research direction

Start in packages/gateway-core/src/workers-ai-errors.ts and inspect WORKERS_AI_ERROR_CODE_TO_STATUS together with normalizeBindingError. Exercise the binding run path with the supplied 3021 error, then verify streaming and non-streaming binding errors and native AI SDK streamText and generateText retry as HTTP 429 while invalid input, unknown errors, and cancellation remain non-retrying.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, backend
Issue type
Bug
Difficulty
1/5
Estimated time
Under an hour
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
92/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.