windmill-labs/windmill · error · Error

State path not set

Error message

State path not set

What it means

getStatePath reads the run's state path from WM_STATE_PATH_NEW (or legacy WM_STATE_PATH). These are set by the Windmill worker when the run has state persistence configured. If neither variable is defined the function throws this Error, blocking state get/set operations.

Source

Thrown at backend/windmill-runtime-nativets/src/windmill-client.js:10012

    endpoint = `/w/${getWorkspace()}/jobs/run/h/${hash_}`;
  } else {
    throw new Error("path or hash_ must be provided");
  }
  let url = new URL(OpenAPI.BASE + endpoint);
  url.search = new URLSearchParams(params).toString();
  return fetch(url, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${OpenAPI.TOKEN}`,
    },
    body: JSON.stringify(args),
  }).then((res) => res.text());
}
function getStatePath() {
  const state_path = getEnv("WM_STATE_PATH_NEW") ?? getEnv("WM_STATE_PATH");
  if (state_path === void 0) {
    throw Error("State path not set");
  }
  return state_path;
}
async function setResource(value, path, initializeToTypeIfNotExist) {
  !clientSet && setClient();
  path = path ?? getStatePath();
  const workspace = getWorkspace();
  if (await ResourceService.existsResource({ workspace, path })) {
    await ResourceService.updateResourceValue({
      workspace,
      path,
      requestBody: { value },
    });
  } else if (initializeToTypeIfNotExist) {
    await ResourceService.createResource({
      workspace,
      requestBody: { path, value, resource_type: initializeToTypeIfNotExist },
    });

View on GitHub (pinned to e474e8803c)

Solutions

  1. Use state functions inside a flow with state persistence enabled so the worker sets WM_STATE_PATH
  2. Pass an explicit path argument instead of relying on the state-path default (setResource(value, path, ...))
  3. Set WM_STATE_PATH manually in local/test environments to a valid resource path
  4. Upgrade the worker/runtime so WM_STATE_PATH_NEW is injected correctly

Example fix

// before
await setState({ count: 1 }); // requires WM_STATE_PATH
// after
await setResource({ count: 1 }, 'u/admin/my_state', 'state'); // explicit path
Defensive patterns

Strategy: validation

Validate before calling

if (process.env.WM_STATE_PATH_NEW === undefined && process.env.WM_STATE_PATH === undefined) {
  throw new Error('state persistence unavailable: WM_STATE_PATH not set');
}

Type guard

function hasStatePath(env) { return typeof (env.WM_STATE_PATH_NEW ?? env.WM_STATE_PATH) === 'string'; }

Try / catch

try {
  await setState(state);
} catch (e) {
  if (e.message === 'State path not set') await setResource(state, fallbackPath, 'state');
  else throw e;
}

Prevention

When it happens

Trigger: Calling getStatePath() directly, or any function defaulting path to getStatePath() (setResource/setState/getState) outside a run with a state path — e.g. outside Windmill, or in a run type that doesn't assign state (plain script without flow state), or env vars removed by the runner.

Common situations: Using setState()/getState() in a standalone script rather than inside a flow with state persistence; running locally without WM_STATE_PATH; older Windmill versions that only set WM_STATE_PATH which has since been deprecated/renamed; tests executing the client directly.

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


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/a7fa21addcbb3f7c. Report an issue: GitHub.