windmill-labs/windmill · error

not a flow

Error message

not a flow

What it means

During `wmill app dev`/`flow dev` setup, `loadWmPath` probes candidate directories for a flow directory and its flow.yaml. If after all probes neither `flowDir` nor `flowYaml` was resolved, it throws 'not a flow' — meaning the current directory layout does not correspond to a pulled/checked-out Windmill flow, so dev mode cannot load it.

Source

Thrown at cli/src/commands/dev/dev.ts:466

  };

  // Load a resource by its windmill path (e.g., "u/admin/my_script" or "f/my_flow")
  async function loadWmPath(wmPath: string): Promise<LastEditScript | LastEditFlow | undefined> {
    wmPath = normalizeWmPath(wmPath);
    // Try as flow — check both dotted and non-dotted suffixes
    let flowDir: string | undefined;
    let flowYaml: string | undefined;
    for (const suffix of [".flow", "__flow"]) {
      const candidate = wmPath + suffix + "/";
      try {
        await access(candidate + "flow.yaml");
        flowDir = candidate;
        flowYaml = candidate + "flow.yaml";
        break;
      } catch {}
    }
    try {
      if (!flowDir || !flowYaml) throw new Error("not a flow");
      const localFlow = (await yamlParseFile(flowYaml)) as FlowFile;
      await replaceInlineScripts(
        localFlow.value.modules,
        async (p: string) => await readTextFile(flowDir + p),
        log,
        flowDir,
        SEP,
        undefined,
      );
      snapshotPathScripts(localFlow.value);
      const localScriptReader = createPreviewLocalScriptReader({
        exts,
        defaultTs: opts.defaultTs,
        codebases,
      });
      await replaceAllPathScriptsWithLocal(localFlow.value, localScriptReader, log);
      tagReplacedPathScripts(localFlow.value);
      const edit: LastEditFlow = {

View on GitHub (pinned to e474e8803c)

Solutions

  1. cd into the flow directory that contains flow.yaml (or its parent the probe expects).
  2. Re-pull the flow with `wmill flow pull` to recreate the expected layout.
  3. Verify you're using the right dev command for the asset type (flow vs script vs app).

Example fix

// before
wmill dev   # run in repo root
// after
cd flows/my_flow && wmill dev
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'node:fs';
if (!existsSync('flow.yaml')) throw new Error('not in a flow directory: flow.yaml not found in ' + process.cwd());

Type guard

null

Try / catch

try { await dev() } catch (e) { if (e.message === 'not a flow') console.error('cd into a directory containing flow.yaml first'); else throw e; }

Prevention

When it happens

Trigger: Running `wmill dev`/flow dev commands in a directory that isn't a flow checkout: no flow.yaml found at the expected locations, running in a script or app directory instead of a flow directory, or the flow.yaml sits deeper than the probed candidates.

Common situations: Running the dev command from the repo root instead of the flow folder; directory renamed after pulling; flow pulled with an older CLI storing a different layout; mixing up script dev and flow dev commands.

Related errors


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