windmill-labs/windmill · error · Error
Job ID not set
Error message
Job ID not set
What it means
getRootJobId(jobId?) resolves the root (flow-parent) job id for the current run via JobService.getRootJobId. The jobId defaults to the WM_JOB_ID environment variable; if neither the argument nor that env var is available, it throws 'Job ID not set'. This typically means the code ran outside a Windmill job execution context (where WM_JOB_ID is injected).
Source
Thrown at typescript-client/client.ts:154
return undefined;
} else {
throw Error(
`Resource not found at ${path} or not visible to you: ${e.body}`
);
}
}
}
/**
* Get the true root job id
* @param jobId job id to get the root job id from (default to current job)
* @returns root job id
*/
export async function getRootJobId(jobId?: string): Promise<string> {
const workspace = getWorkspace();
jobId = jobId ?? getEnv("WM_JOB_ID");
if (jobId === undefined) {
throw Error("Job ID not set");
}
return await JobService.getRootJobId({ workspace, id: jobId });
}
/**
* @deprecated Use runScriptByPath or runScriptByHash instead
*/
export async function runScript(
path: string | null = null,
hash_: string | null = null,
args: Record<string, any> | null = null,
verbose: boolean = false,
tag: string | null = null
): Promise<any> {
console.warn(
"runScript is deprecated. Use runScriptByPath or runScriptByHash instead."
);
if (path && hash_) {View on GitHub (pinned to e474e8803c)
Solutions
- Run the code inside a Windmill job (script/flow step) so WM_JOB_ID is injected.
- Pass the job id explicitly: getRootJobId('some-job-id') when calling outside a run.
- In local dev, set WM_JOB_ID in the environment to a real job id copied from the runs page.
- Guard flow-state helpers so they no-op outside Windmill: if (!getEnv('WM_JOB_ID')) return.
Example fix
// before const rootId = await getRootJobId() // throws locally // after const rootId = process.env.WM_JOB_ID ? await getRootJobId() : undefined
Defensive patterns
Strategy: validation
Validate before calling
import { getEnv } from 'windmill-client'
if (!jobId && !getEnv('WM_JOB_ID')) {
console.warn('Not running inside a Windmill job; skipping flow state access')
return
}
await getRootJobId(jobId) Type guard
function hasJobContext(jobId?: string): boolean {
return Boolean(jobId ?? process.env.WM_JOB_ID)
} Try / catch
try {
await setFlowUserState(key, value)
} catch (e) {
if (e?.message === 'Job ID not set') {
console.warn('Flow state unavailable outside Windmill jobs')
} else throw e
} Prevention
- Only call flow-state helpers from code executed by a Windmill worker.
- Gate flow-state code with a WM_JOB_ID presence check for locally-run scripts.
- Pass jobId explicitly when invoking from non-job contexts.
- Avoid importing these helpers into unit tests without stubbing the env var.
When it happens
Trigger: Calling getRootJobId() (or setFlowUserState/getFlowUserState, which call it) from code running outside a Windmill worker — local dev, plain Node, tests — or inside a job type that does not set WM_JOB_ID (e.g. some hooks/preview contexts).
Common situations: Running a script locally with `node`/`tsx` to debug flow user state code; unit tests importing the helper; code shared between Windmill jobs and external tooling executing outside the runner; a container image or executor that drops the WM_JOB_ID env var.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- Resource not found at ${path} or not visible to you: ${e.bod
- Invalid note at index ${index}: position must be an object w
- Invalid note at index ${index}: size must be an object with
- Invalid note at index ${index}: contained_node_ids must be a
- Unsupported draft type "${type}".
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/e902589d67f0658f.
Report an issue: GitHub.