workers-sdk icon indicating copy to clipboard operation
workers-sdk copied to clipboard

can't test cron triggers locally with assets or redirected config

Open bryanhpchiang opened this issue 6 months ago • 5 comments

What versions & operating system are you using?

wrangler v4.24.0, node v23.10.0, macOS 15.5

Please provide a link to a minimal reproduction

https://github.com/bryanhpchiang/experiments

Describe the Bug

i just wanted to set up a vite+react project with some cron triggers. unfortunately, i can't test it locally.

pnpm create vite@latest experiments --template react-ts

i then followed this guide to add in the cron triggers code: https://developers.cloudflare.com/workers/configuration/cron-triggers/

(see the linked repo for the changes)

i then try to test it locally by following the guide:

❯ pnpm wrangler dev

 ⛅️ wrangler 4.24.0
───────────────────
Using redirected Wrangler configuration.
 - Configuration being used: "dist/experiments/wrangler.json"
 - Original user's configuration: "wrangler.jsonc"
 - Deploy configuration file: ".wrangler/deploy/config.json"
╭──────────────────────────────────────────────────────────────────────╮
│  [b] open a browser [d] open devtools [c] clear console [x] to exit  │
╰──────────────────────────────────────────────────────────────────────╯
▲ [WARNING] Miniflare does not currently trigger scheduled Workers automatically.

  Refer to https://developers.cloudflare.com/workers/configuration/cron-triggers/#test-cron-triggers
  for more details


⎔ Starting local server...
[wrangler:info] Ready on http://localhost:8787

and then in another tab:

❯ curl "http://localhost:8787/cdn-cgi/handler/scheduled?cron=*+*+*+*+*"

exception%


searching online brings me here: https://github.com/cloudflare/workers-sdk/issues/5548

i try the fix in that issue:

❯ npx wrangler dev --test-scheduled

 ⛅️ wrangler 4.24.0
───────────────────
Using redirected Wrangler configuration.
 - Configuration being used: "dist/experiments/wrangler.json"
 - Original user's configuration: "wrangler.jsonc"
 - Deploy configuration file: ".wrangler/deploy/config.json"
╭──────────────────────────────────────────────────────────────────────╮
│  [b] open a browser [d] open devtools [c] clear console [x] to exit  │
╰──────────────────────────────────────────────────────────────────────╯
⎔ Starting local server...
[wrangler:info] Ready on http://localhost:8787

and in another tab:

❯ curl "http://localhost:8787/__scheduled?cron=*+*+*+*+*"

(base)

and in the first tab there is a 404: [wrangler:info] GET /__scheduled 404 Not Found (3ms)

weird! very confusing docs and experience so far.

Please provide any relevant error logs

No response

bryanhpchiang avatar Jul 08 '25 10:07 bryanhpchiang

Hi, both methods you tried should work, but unfortunately it looks like you've uncovered two or three separate bugs :(

  1. /cdn-cgi/handler/scheduled?cron=*+*+*+*+* is broken for assets.
  • (note for whoever fixes this - at a glance, this is because miniflare's entry worker is trying to call the scheduled handler on the 'fallbackWorker', which is normally the user worker, but with assets involved is actually the asset proxy worker, which doesn't have a scheduled handler.)
  1. /__scheduled with the --test-scheduled flag is broken for vite apps with redirected config, even when using wrangler.
  • (note for whoever fixes this - this is because vite does not bundle in the middleware that simulates the scheduled handler.)
  1. the third one isn't a bug, just unintuitive DX :( not_found_handling: 'single-page-application' means that when you navigate to /__scheduled in the browser your worker isn't triggered and we fallback back to index.html. you can get around this by curling the scheduled testing endpoint.

As a very hacky workaround until we fix this, you can do this:

  1. build using wrangler with npx wrangler deploy --dry-run -c wrangler.jsonc --outdir=cron-test
  2. update your wrangler config to use the built values for main and assets.directory, or create a new one with the built values just for testing crons. e.g. wrangler.cron.jsonc:
	"name": "experiments",
	"main": "temp/index.js",
	"compatibility_date": "2025-07-08",
	"assets": {
		"directory": "dist/client",
		"not_found_handling": "single-page-application",
	},
	"triggers": {
		"crons": [
			"* * * * *"
		]
	},
  1. force wrangler dev to run with that wrangler config instead of the redirected one with npx wrangler deploy --dry-run -c wrangler.cron.jsonc

Sorry you've hit these issues, but also thank you for finding and reporting this!

emily-shen avatar Jul 14 '25 14:07 emily-shen

thanks for the detailed breakdown :~)

On Mon, Jul 14, 2025 at 7:22 AM, emily-shen < @.*** > wrote:

emily-shen left a comment (cloudflare/ workers-sdk#9882) ( https://github.com/cloudflare/workers-sdk/issues/9882#issuecomment-3069802841 )

Hi, both methods you tried should work, but unfortunately it looks like you've uncovered two or three separate bugs :(

  • /cdn-cgi/handler/scheduled?cron=++++* is broken for assets.

  • (note for whoever fixes this - at a glance, this is because miniflare's entry worker is trying to call the scheduled handler on the 'fallbackWorker', which is normally the user worker, but with assets involved is actually the asset proxy worker, which doesn't have a scheduled handler.)

  • /__scheduled with the --test-scheduled flag is broken for vite apps with redirected config, even when using wrangler.

  • (note for whoever fixes this - this is because vite does not bundle in the middleware that simulates the scheduled handler.)

  • the third one isn't a bug, just unintuitive DX :( not_found_handling: 'single-page-application' means that when you navigate to /__scheduled in the browser your worker isn't triggered and we fallback back to index.html. you can get around this by curling the scheduled testing endpoint.

As a very hacky workaround until we fix this, you can do this:

  • build using wrangler with npx wrangler deploy --dry-run -c wrangler.jsonc --outdir=cron-test
  • update your wrangler config to use the built values for main and assets. directory ( http://assets.directory/ ) , or create a new one with the built values just for testing crons. e.g. wrangler.cron.jsonc: "name": "experiments", "main": "temp/index.js", "compatibility_date": "2025-07-08", "assets": { "directory": "dist/client",

"not_found_handling": "single-page-application", }, "triggers": {

"crons": [ "* * * * *" ] },

  • force wrangler dev to run with that wrangler config instead of the redirected one with npx wrangler deploy --dry-run -c wrangler.cron.jsonc

Sorry you've hit these issues, but also thank you for finding and reporting this!

— Reply to this email directly, view it on GitHub ( https://github.com/cloudflare/workers-sdk/issues/9882#issuecomment-3069802841 ) , or unsubscribe ( https://github.com/notifications/unsubscribe-auth/AXMEJMCWXPHEF3AP6WKA3GL3IO4MDAVCNFSM6AAAAACBAXRNZWVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTANRZHAYDEOBUGE ). You are receiving this because you authored the thread. Message ID: <cloudflare/workers-sdk/issues/9882/3069802841 @ github. com>

bryanhpchiang avatar Jul 14 '25 20:07 bryanhpchiang

I'm seeing something similar trying to test an Email Worker in a project that also uses the vite plugin. I'm chiming in because I think there's one other bug. Because wrangler dev is using: "dist/experiments/wrangler.json", it will also use the built worker file in dist/experiments. That means any changes you make to your worker file aren't reflected until you do another vite build. You can work around this by deleting .wrangler/deploy so it stops looking at the config in dist.

joshcartme avatar Jul 27 '25 19:07 joshcartme

The workaround I have now is

  • Add a route in fetch handler (e.g. when using hono app.post("/dev/cron" ....) to trigger the cron logic directly. Only mount/enable the handler for dev env.
  • Write another script to setInterval and call that route.
  • Run vite and the script in parallel e.g. using https://www.npmjs.com/package/concurrently in package.json
"scripts": {
     "dev": "concurrently 'vite' 'node trigger-cron.js'"
}

at15 avatar Oct 12 '25 03:10 at15

What works 🚀 🦀

Configure ASSETS binding to bypass /__scheduled to the worker.

  "assets": {
    "binding": "ASSETS",
    "directory": "./dist/",
    "not_found_handling": "single-page-application",
    "run_worker_first": ["/__scheduled", "/api/*", "!/api/docs/*"],
  },

Run vite and wrangler separately, for example with concurrently package: concurrently --names vite,wran -c blue,yellow 'vite' 'wrangler dev --test-scheduled'. Here is package.json script command

  "scripts": {
    "dev": "concurrently --names vite,wran -c blue,yellow 'vite' 'wrangler dev --test-scheduled'"
  }

Note, you need to use --test-scheduled.

vite plugins config must not include cloudflare vite plugin

export default defineConfig({
  clearScreen: false,
  plugins: [tailwindcss(), react(), tsconfigPaths()],
});

Note, I do not like to use react-router plugin so can't say if above solution will work with react-router plugin.

Use http://localhost:<your port usually 8787>/__scheduled to test your cron jobs

This worked for me with wranger 4.53.0

dmshvetsov avatar Dec 05 '25 17:12 dmshvetsov