Repository navigation
React Router, TanStack Start and vinext dev: a cron that imports defineScheduled from 'void' breaks every dev trigger #417
Description
Problem
The jobs and queues guides show this import (docs/guide/jobs.md:22, docs/guide/queues.md:19):
import { defineScheduled } from 'void';In a React Router, TanStack Start or vinext app, vp dev cannot load a cron or queue file with this import. A POST to /__void/scheduled returns 500:
The file does not exist at ".../node_modules/.vite/deps_ssr/jiti.js?v=f8fc50fd" which is in the
optimize deps directory. The dependency might be incompatible with the dep optimizer. Try adding
it to `optimizeDeps.exclude`.
The terminal shows why. Bare void loaded the Vite plugin itself, and the dependency optimizer tried to bundle Wrangler into the worker:
(ssr) error while updating dependencies:
Error: Error during dependency optimization:
Build failed with 1 error:
[UNRESOLVED_IMPORT] Could not resolve './node.js' in .../blake3-wasm/esm/index.js
imported by .../wrangler/wrangler-dist/cli.js
imported by .../@cloudflare/vite-plugin/dist/index.mjs
One such file breaks every dev cron and queue trigger, because the generated dispatch module imports all of them. Pages still return 200. Production builds are fine, because the cron bundle maps bare void to void/handler.
Repro
- Copy
playground/react-router. - Add
crons/tick.ts:import { defineScheduled } from 'void'; export const cron = '*/5 * * * *'; export default defineScheduled(async () => { console.log('tick ran'); });
- Run
vp dev, then:curl -X POST http://localhost:5173/__void/scheduled \ -H "x-void-dev-trigger: $(cat .void/dev-trigger-token)" \ -d '{"cron":"*/5 * * * *","scheduledTime":'"$(date +%s000)"'}'
- The response is 500 with the message above, on every try.
Cause
Bare void resolves to the package entry, dist/index.mjs, which is the Vite plugin. Other paths redirect it to the light void/handler entry, but the React Router, TanStack Start and vinext plugin list has no such redirect:
| Where | Redirects bare void |
|---|---|
Void apps (packages/void/src/plugin-routing.ts:603-607) |
yes |
SvelteKit dev (packages/void/src/plugin-framework.ts:234-246, added in #413) |
yes |
Production cron/queue bundle (packages/void/src/cli/wrapper.ts:142-147) |
yes |
React Router, TanStack Start, vinext (packages/void/src/index.ts:727-767) |
no |
The dev dispatch module imports each cron file into the framework's workerd environment (packages/void/src/plugin-framework-triggers.ts:114).
Suggested fix
Add the same resolveId redirect to the React Router, TanStack Start and vinext plugin list: order pre, filter ^void$, server environments only, resolve to void/handler. Add a dev integration test with a cron that imports defineScheduled from 'void'.
Evidence
- Reproduced once at the head of fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413 with a copy of
playground/react-router(workspace-linkedvoid), using the steps above. Three POSTs returned 500;GET /returned 200. - Code read at origin/main: the plugin list (
index.ts:727-767) and the production alias (wrapper.ts:131) are the same, so main behaves the same way. - Not changed by fix(void): make PostgreSQL and MySQL void/db work across frameworks, builds and deploys #413.
🤖 Generated with Claude Code
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Activity
fix(void): give framework dev crons the handler exports of bare void,…
fix(void): give framework dev crons the handler exports of bare void,…
fix(void): give framework dev crons the handler exports of bare void,…
fix(void): give framework dev crons the handler exports of bare void,…
fix(void): give framework dev crons the handler exports of bare void,…