cloudflare / cloudflare/workers-sdk
_redirects: dynamic-rule overflow silently drops rest of file; static/dynamic classification is order-dependent and unsurfaced
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 186
Description
## Which Cloudflare product(s) does this pertain to?
Workers, Pages (static assets `_redirects` handling in `packages/workers-shared`)
## What is the issue or request?
The `_redirects` parser silently drops the remainder of a file once the dynamic-rule budget is exceeded, and the static/dynamic classification depends on rule ordering in a way that is not surfaced to the user at build or deploy time.
In [`parseRedirects.ts`](https://github.com/cloudflare/workers-sdk/blob/main/packages/workers-shared/utils/configuration/parseRedirects.ts):
- `canCreateStaticRule` starts `true` and is set to `false` permanently the first time a rule containing a splat (`*`) or placeholder (`:name`) is encountered.
- After that point, every subsequent rule — including exact-path rules that would otherwise be static — is counted against the 100 dynamic-rule budget.
- When `dynamicRules > maxDynamicRules` (100), the parser `break`s and skips all remaining lines, including any catch-all at the end of the file. The `invalid` entry records this, but nothing surfaces it to the user during `wrangler deploy`.
The documented limit of "2,000 static + 100 dynamic" is therefore only achievable if the entire file is ordered static-first. A single dynamic rule placed early collapses the effective static budget, and a file with more than 100 rules after the first dynamic rule loses its tail with no visible error.
This was reported publicly here: https://x.com/samuelcolvin/status/2076993431818084700 — a large `_redirects` file 404'd everything after the point where the dynamic budget overflowed, including the catch-all, with no build-time signal.
## Requested changes
Two options, not mutually exclusive:
1. **Non-breaking: surface a warning at build/deploy time.** Emit a warning from `wrangler deploy` (and `wrangler dev`) when:
- the dynamic-rule limit is exceeded and lines are skipped, or
- static rules appear after a dynamic rule (so they are being counted as dynamic).
The `invalid` messages already contain this information; they just are not surfaced. This changes no runtime behaviour.
2. **Behavioural fix, gated behind a compatibility date / `redirects.version`.** Classify rules by their own shape (splat/placeholder → dynamic, otherwise static) regardless of position, so exact-path rules after a dynamic rule are counted and matched as static.
This is a breaking change and should not apply to already-deployed configs:
- Previously-dropped rules would start firing.
- Precedence would change: `staticRedirectsMatcher` (exact-map) is evaluated before `generateRedirectsMatcher` (ordered regex) in [`rules-engine.ts`](https://github.com/cloudflare/workers-sdk/blob/main/packages/workers-shared/asset-worker/src/utils/rules-engine.ts), so reclassifying an exact-path rule that currently sits after a splat would move it ahead of that splat and can change which redirect wins for overlapping paths — even in files that never approach the limit.
The existing `redirects.version` gate in `generateRedirectsMatcher` and/or a compatibility date would let new deployments opt into the new semantics while existing deployments keep current behaviour.
## Docs
The current behaviour is being documented in cloudflare-docs (the `_redirects` "Per file" section) so that the ordering requirement and the silent-drop behaviour are explicit in the meantime: https://github.com/cloudflare/cloudflare-docs/pull/32083
Contributor guide
Research direction
Start in packages/workers-shared/utils/configuration/parseRedirects.ts and trace how invalid entries are produced when the dynamic-rule limit is exceeded. Then read packages/workers-shared/asset-worker/src/utils/rules-engine.ts and the Wrangler deploy/dev paths to see how diagnostics and redirects.version are handled. Done means the agreed warning or compatibility-gated classification behavior is covered without changing unintended existing behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100