package.json:14 fans the development command across every workspace:
"dev": "bun run generate:app-config && bun run --filter '*' --parallel dev",
workspaces is ["app", "server", "worker"], so '*' selects three packages and the third one cannot start. worker/package.json runs bun --watch src/index.ts with its working directory set to worker/, so Bun reads worker/.env, which does not exist. The repository's own .env is never seen — server/package.json passes --env-file=../.env for exactly this reason, and the worker's script does not.
Every bun run dev therefore prints a stack trace in between the app's output and the server's:
worker dev | error: WORKER_SHARED_SECRET is not set, so this worker cannot authenticate
worker dev | itself to /internal/routines/run and no routine could be fired.
worker dev | at loadWorkerEnv (worker/src/env.ts:32:15)
worker dev | at worker/src/index.ts:52:3
Setting the secret in the root .env changes nothing, because the worker still does not read that file. Passing --env-file=../.env does not rescue a fresh clone either: .env.example:340 ships WORKER_SHARED_SECRET= empty on purpose — "Left empty, the internal endpoint refuses every call and no routine ever fires — the correct state for a deployment that has not stood up a worker" — and empty fails the same ?.trim() guard at worker/src/env.ts:30. This worker has never started on any machine; worker/package.json has a single commit in its history.
What the command is documented to do
README.md:339 and docs/development.md:34 both scope it to two processes:
Use bun run dev only when you want the app and API server without starting the Docker Bots and computers.
The worker's own source names its launcher at worker/src/index.ts:46:
This process is handed exactly three settings by scripts/start.sh (DATABASE_URL, SERVER_INTERNAL_URL, WORKER_SHARED_SECRET)
scripts/start.sh:335 starts it from the repository root with those three set, and that path works.
Why making it start would be worse
scripts/start.sh:329 explains that its guard matches bun worker/src/index.ts specifically, because cd worker && bun src/index.ts also matches three Dockerfiles and made the guard false-positive. A worker started by bun run dev runs under precisely that argv, so pgrep would miss it and start.sh would start a second one beside it. Two workers on one machine claiming the same routine is a failure this repository has already had to fix once.
Reproduction
On a clean checkout of main:
bun install
bun run --filter worker dev
That is the exact command --filter '*' runs for the worker. It throws at boot, with or without a populated .env.
Severity
Low, and confined to local development. Nothing a deployment does changes: Kubernetes fires routines from the CronJob and a laptop fires them from scripts/start.sh. The cost is a fatal error on every bun run dev, and a developer who reasonably reads it as a broken checkout — or who assumes the command gave them a worker, when docs/routines.md warns that a missing worker shows nothing on screen.
package.json:14fans the development command across every workspace:workspacesis["app", "server", "worker"], so'*'selects three packages and the third one cannot start.worker/package.jsonrunsbun --watch src/index.tswith its working directory set toworker/, so Bun readsworker/.env, which does not exist. The repository's own.envis never seen —server/package.jsonpasses--env-file=../.envfor exactly this reason, and the worker's script does not.Every
bun run devtherefore prints a stack trace in between the app's output and the server's:Setting the secret in the root
.envchanges nothing, because the worker still does not read that file. Passing--env-file=../.envdoes not rescue a fresh clone either:.env.example:340shipsWORKER_SHARED_SECRET=empty on purpose — "Left empty, the internal endpoint refuses every call and no routine ever fires — the correct state for a deployment that has not stood up a worker" — and empty fails the same?.trim()guard atworker/src/env.ts:30. This worker has never started on any machine;worker/package.jsonhas a single commit in its history.What the command is documented to do
README.md:339anddocs/development.md:34both scope it to two processes:The worker's own source names its launcher at
worker/src/index.ts:46:scripts/start.sh:335starts it from the repository root with those three set, and that path works.Why making it start would be worse
scripts/start.sh:329explains that its guard matchesbun worker/src/index.tsspecifically, becausecd worker && bun src/index.tsalso matches three Dockerfiles and made the guard false-positive. A worker started bybun run devruns under precisely that argv, sopgrepwould miss it andstart.shwould start a second one beside it. Two workers on one machine claiming the same routine is a failure this repository has already had to fix once.Reproduction
On a clean checkout of
main:That is the exact command
--filter '*'runs for the worker. It throws at boot, with or without a populated.env.Severity
Low, and confined to local development. Nothing a deployment does changes: Kubernetes fires routines from the CronJob and a laptop fires them from
scripts/start.sh. The cost is a fatal error on everybun run dev, and a developer who reasonably reads it as a broken checkout — or who assumes the command gave them a worker, whendocs/routines.mdwarns that a missing worker shows nothing on screen.