Provide environment information
System:
OS: macOS 26.6
CPU: (14) arm64 Apple M4 Pro
Memory: 454.95 MB / 48.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.14.0 - /Users/cheema/.local/state/fnm_multishells/3536_1784491292657/bin/node
Yarn: 1.22.22 - /opt/homebrew/bin/yarn
npm: 11.9.0 - /Users/cheema/.local/state/fnm_multishells/3536_1784491292657/bin/npm
pnpm: 10.25.0 - /opt/homebrew/bin/pnpm
bun: 1.3.5 - /Users/cheema/.bun/bin/bun
trigger.dev CLI 4.5.4, @trigger.dev/sdk 4.5.4
Describe the bug
I hit this while setting up a new project. I had trigger dev running, started another dev session for the same project, and the new one crashed mid-build with an uncaught ENOENT writing to .trigger/tmp/store/<hash> (screenshot below, stack included).
Digging into the CLI source, here is what I believe happens. getStoreDir() (packages/cli-v3/src/utilities/tempDirectories.ts) creates .trigger/tmp/store when a dev session starts and registers an exit handler that deletes it recursively. The path is deterministic per project and branch, so every dev session of the same project shares it. When you start a second session, the takeover makes the first one exit, and its cleanup deletes the store out from under the new session. createFileWithStore() (packages/cli-v3/src/utilities/fileSystem.ts) ensures the build file's parent directory before writing, but not the store directory, so the next store write fails.
The timing decides what you see. If the cleanup lands during the new session's initial build, it crashes loudly like mine did. If it lands later, the next watch rebuild prints "Rebuilding local worker…" and hangs forever with no error output, which is the nastier version; that one reproduces deterministically. And if the old process happens to die without running its cleanup, nothing breaks at all, which is probably why this can look intermittent.
Reproduction repo
Not project-specific: reproduces on any project with the steps below (it's a CLI dev-session race, no special code involved).
To reproduce
Organic: run npx trigger.dev@latest dev, wait for "Local worker ready", then start a second trigger dev for the same project in another terminal. Depending on where the old session's cleanup lands, the new session either crashes with the ENOENT mid-build (screenshot) or hangs silently on a later rebuild.
Deterministic shortcut for the hang variant: with one dev session running, delete .trigger/tmp/store (the same deletion the exit cleanup performs), then make any content change to a task file. The rebuild starts and never finishes, with no error output.
Additional information
A one-line fix works: ensure the store directory exists in createFileWithStore right before the store write, the same way the function already ensures the build path a few lines earlier. I patched my local install with it and the exact repro heals: the rebuild completes and the store gets repopulated. Happy to open that PR with a regression test once vouched.
One side observation from debugging: watch-rebuild errors seem to get swallowed entirely, which is what turns this case into a silent hang instead of a visible error.

Provide environment information
System:
OS: macOS 26.6
CPU: (14) arm64 Apple M4 Pro
Memory: 454.95 MB / 48.00 GB
Shell: 5.9 - /bin/zsh
Binaries:
Node: 24.14.0 - /Users/cheema/.local/state/fnm_multishells/3536_1784491292657/bin/node
Yarn: 1.22.22 - /opt/homebrew/bin/yarn
npm: 11.9.0 - /Users/cheema/.local/state/fnm_multishells/3536_1784491292657/bin/npm
pnpm: 10.25.0 - /opt/homebrew/bin/pnpm
bun: 1.3.5 - /Users/cheema/.bun/bin/bun
trigger.dev CLI 4.5.4, @trigger.dev/sdk 4.5.4
Describe the bug
I hit this while setting up a new project. I had
trigger devrunning, started another dev session for the same project, and the new one crashed mid-build with an uncaught ENOENT writing to.trigger/tmp/store/<hash>(screenshot below, stack included).Digging into the CLI source, here is what I believe happens.
getStoreDir()(packages/cli-v3/src/utilities/tempDirectories.ts) creates.trigger/tmp/storewhen a dev session starts and registers an exit handler that deletes it recursively. The path is deterministic per project and branch, so every dev session of the same project shares it. When you start a second session, the takeover makes the first one exit, and its cleanup deletes the store out from under the new session.createFileWithStore()(packages/cli-v3/src/utilities/fileSystem.ts) ensures the build file's parent directory before writing, but not the store directory, so the next store write fails.The timing decides what you see. If the cleanup lands during the new session's initial build, it crashes loudly like mine did. If it lands later, the next watch rebuild prints "Rebuilding local worker…" and hangs forever with no error output, which is the nastier version; that one reproduces deterministically. And if the old process happens to die without running its cleanup, nothing breaks at all, which is probably why this can look intermittent.
Reproduction repo
Not project-specific: reproduces on any project with the steps below (it's a CLI dev-session race, no special code involved).
To reproduce
Organic: run
npx trigger.dev@latest dev, wait for "Local worker ready", then start a secondtrigger devfor the same project in another terminal. Depending on where the old session's cleanup lands, the new session either crashes with the ENOENT mid-build (screenshot) or hangs silently on a later rebuild.Deterministic shortcut for the hang variant: with one dev session running, delete
.trigger/tmp/store(the same deletion the exit cleanup performs), then make any content change to a task file. The rebuild starts and never finishes, with no error output.Additional information
A one-line fix works: ensure the store directory exists in
createFileWithStoreright before the store write, the same way the function already ensures the build path a few lines earlier. I patched my local install with it and the exact repro heals: the rebuild completes and the store gets repopulated. Happy to open that PR with a regression test once vouched.One side observation from debugging: watch-rebuild errors seem to get swallowed entirely, which is what turns this case into a silent hang instead of a visible error.