Skip to content

fix(deploy): leave out run_worker_first rules that a wider rule already covers - #763

Merged
cpojer merged 1 commit into
voidzero-dev:mainfrom
morinokami:fix/static-run-worker-first-overlap
Nov 9, 2026
Merged

cpojer merged 1 commit into
voidzero-dev:mainfrom
morinokami:fix/static-run-worker-first-overlap

Conversation

@morinokami

Copy link
Copy Markdown
Collaborator

Since #660 (1.6.0), an output: "static" Pages build lists only the paths with server code in run_worker_first, so prerendered pages and public files are served without starting the Worker. Each pattern is widened to its static prefix before the first parameter (/blog/:slug → /blog/*). When one server path sits under another one's /prefix/* rule, both rules are written. For example, with two dynamic pages under /blog/:

pages/blog/[slug].tsx       -> /blog/*
pages/blog/tags/[tag].tsx   -> /blog/tags/*

vp build succeeds without a warning, but Cloudflare rejects the list. vp preview exits with a Miniflare error, and wrangler deploy refuses the built output with the same message:

Error: Invalid routes in `run_worker_first`:
'/blog/tags/*': rule '/blog/*' makes it redundant

A dynamic API route next to the starter's routes/api/hello.ts fails the same way (/api/* and /api/hello). Apps without output: "static", and static apps that use middleware, auth, live updates, routing.alwaysUseHttps or edge rules, get a list that starts with /** and are not affected.

Fix

The planner now leaves out every rule that a /prefix/* rule in the list already matches. The wider rule sends the same requests to the Worker, so routing does not change.

  • This also covers server paths under the /assets/* rule that a build adds when it cannot list its hashed files in _headers.
  • /proxy stays next to /proxy/*, and /api-docs next to /api/*: neither starts with the wider rule's /prefix/.

Tests

  • packages/void/test/unit/asset-worker-bypass.test.ts: nested wildcards, exact paths and a catch-all under a wildcard, a path below a trailing-wildcard route, and a server path under the /assets/* rule each keep only the wider rule. Both new cases fail without this fix.
  • packages/void/test/integration/native-asset-cache-policy.test.ts: the output: "static" case passes the planner's list to Miniflare, which checks run_worker_first with the same code as wrangler. It now adds /items/tags/:tag and /api/:name next to /items/:id and /api/hello, and checks that /items/tags/new and /api/someone reach the Worker. Without this fix, Miniflare rejects the list ('/api/hello': rule '/api/*' makes it redundant).

Verification

  • vp test run: 788 files pass, 1 skipped (16,467 tests pass, 30 skipped).
  • vp run check: 33/33 pass.
  • By hand on a copy of playground/static-pages with pages/posts/tags/[tag] next to pages/posts/[slug], and routes/api/[name].ts next to routes/api/hello.ts:
    • Without this fix, vp build passes without a warning and writes /api/*, /api/hello, /posts/* and /posts/tags/* to run_worker_first. vp preview exits with '/api/hello': rule '/api/*' makes it redundant and '/posts/tags/*': rule '/posts/*' makes it redundant, and wrangler deploy --dry-run (4.158.0) fails with the same errors.
    • With it, the list keeps only /api/* and /posts/*. vp preview starts: /posts/tags/news renders its page, /api/hello and /api/someone answer from their own handlers, and a POST to /plain still answers 405 from the asset layer. wrangler deploy --dry-run passes.
  • Not run: void deploy against Cloudflare.

🤖 Generated with Claude Code

…dy covers

An `output: "static"` Pages build lists only the paths with server code
in `run_worker_first`, each widened to its static prefix before the
first parameter. When one server path sits under another one's
`/prefix/*` rule, both rules were written:

```
pages/blog/[slug].tsx       -> /blog/*
pages/blog/tags/[tag].tsx   -> /blog/tags/*
```

Cloudflare rejects that list ("'/blog/tags/*': rule '/blog/*' makes it
redundant"). `vp build` succeeded, but `vp preview` exited and
`wrangler deploy` refused the output. A dynamic API route next to the
starter's `routes/api/hello.ts` (`/api/*` and `/api/hello`) failed the
same way. This affected such apps since 1.6.0 (voidzero-dev#660).

The planner now leaves out every rule that a `/prefix/*` rule in the
list already matches, including server paths under the assets folder
rule that a build adds when it cannot list its hashed files. The wider
rule sends the same requests to the Worker, so routing does not change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@cpojer
cpojer self-requested a review November 9, 2026 23:37

@cpojer cpojer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!

@cpojer
cpojer merged commit 0d31e94 into voidzero-dev:main Nov 9, 2026
2 checks passed
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.

2 participants