Provide environment information
n/a
Describe the bug
Calling configure() per-request is not safe in parallel contexts (React server actions, Promise.all, etc.). The bug is more severe than a simple overwrite race: configure() calls registerGlobal without allowOverride, so any call after the first is silently dropped. The caller gets no error, no warning, and unknowingly uses the wrong token.
Both runs triggered in parallel end up in the same project (whichever request called configure() first).
Expected: each request uses its own token/project.
Actual: second configure() call returns false silently; both requests use the first token
Reproduction repo
n/a
To reproduce
import "dotenv/config";
import { configure, tasks } from "@trigger.dev/sdk";
const tokenA = process.env.TRIGGER_TOKEN_A;
const tokenB = process.env.TRIGGER_TOKEN_B;
async function simulateRequest(label: string, token: string) {
configure({ accessToken: token });
await new Promise((r) => setImmediate(r)); // simulates any real async yield
const run = await tasks.trigger("fast-task", { i: label });
console.log(`${label} triggered run: ${run.id}`);
return { label, token, runId: run.id };
}
const results = await Promise.all([
simulateRequest("token-A", tokenA),
simulateRequest("token-B", tokenB),
]);
// Both runs appear in token-A's project dashboard, token-B's project gets nothing.
Set TRIGGER_TOKEN_A and TRIGGER_TOKEN_B to tokens from two different projects, then check both dashboards.
Additional information
Workaround:
Use auth.withAuth() per request instead of configure(). Note: withAuth uses runWithConfig which passes allowOverride = true, so it does write the config, but save/restore around an async function is still not safe across concurrent calls.
Fix direction:
AsyncLocalStorage (or equivalent) for per-async-context config isolation.
Provide environment information
n/a
Describe the bug
Calling
configure()per-request is not safe in parallel contexts (React server actions, Promise.all, etc.). The bug is more severe than a simple overwrite race:configure()callsregisterGlobalwithoutallowOverride, so any call after the first is silently dropped. The caller gets no error, no warning, and unknowingly uses the wrong token.Both runs triggered in parallel end up in the same project (whichever request called configure() first).
Expected: each request uses its own token/project.
Actual: second
configure()call returns false silently; both requests use the first tokenReproduction repo
n/a
To reproduce
Set TRIGGER_TOKEN_A and TRIGGER_TOKEN_B to tokens from two different projects, then check both dashboards.
Additional information
Workaround:
Use auth.withAuth() per request instead of configure(). Note: withAuth uses runWithConfig which passes allowOverride = true, so it does write the config, but save/restore around an async function is still not safe across concurrent calls.
Fix direction:
AsyncLocalStorage (or equivalent) for per-async-context config isolation.