windmill-labs/windmill · error
Flow path must be a .flow/__flow directory or a flow.yaml fi
Error message
Flow path must be a .flow/__flow directory or a flow.yaml file
What it means
`wmill flow preview` requires the given path to point either at a `.flow/__flow` directory (a folder containing flow assets) or a `flow.yaml`/`flow.json` file. Any other path form is rejected with this error before any file reading happens.
Source
Thrown at cli/src/commands/flow/flow.ts:636
const workspace = await resolveWorkspace(opts);
await requireLogin(opts);
const codebases = useLocalPathScripts ? listSyncCodebases(opts) : [];
const argPath = flowPath;
flowPath = toSyncRootRelativePath(flowPath, cwdBeforeConfig);
// Normalize path - ensure it's a directory path to a .flow or __flow folder
const isFlowDir = flowPath.endsWith(".flow") || flowPath.endsWith(".flow" + SEP)
|| flowPath.endsWith("__flow") || flowPath.endsWith("__flow" + SEP);
if (!isFlowDir) {
// Check if it's a flow.yaml file
if (flowPath.endsWith("flow.yaml") || flowPath.endsWith("flow.json")) {
// Use dirname so a bare "flow.yaml" (no parent dir) becomes "."
// instead of "" — the latter, after appending SEP below, becomes "/"
// and silently reads from filesystem root.
flowPath = dirname(flowPath);
} else {
throw new Error(
"Flow path must be a .flow/__flow directory or a flow.yaml file"
);
}
}
if (!flowPath.endsWith(SEP)) {
flowPath += SEP;
}
// The flow's windmill path (e.g. "f/cli_smoke/myrelflow"). It is what the
// preview job runs under, and the anchor for relative-import resolution:
// inline scripts in this flow are treated as living at
// "<flow_wm_path>/<step_id>", so "./util" resolves to
// "<flow_wm_path_parent>/util" — matching the keys in temp_script_refs.
const flowWmPath = stripFlowSuffix(flowPath).replaceAll(SEP, "/");
assertRemotePath(flowWmPath, argPath);
// Read and parse the flow definitionView on GitHub (pinned to e474e8803c)
Solutions
- Point the command at the `*.flow/__flow` directory created by `wmill flow bootstrap`
- Rename the file to `flow.yaml` (or `flow.json`) — `.yml` is not accepted
- Pass the directory, not an arbitrary parent folder
Example fix
// before wmill flow preview myflows/etl/flow.yml // after wmill flow preview myflows/etl/flow.yaml
Defensive patterns
Strategy: validation
Validate before calling
const ok = flowPath.endsWith('.flow/__flow') || flowPath.endsWith('flow.yaml') || flowPath.endsWith('flow.json');
if (!ok) throw new Error(`flow path must be a .flow/__flow dir or flow.yaml/json: got ${flowPath}`); Prevention
- Always bootstrap flows with `wmill flow bootstrap` so the directory layout is canonical
- Use `.yaml` extension, never `.yml`
- Quote paths in shell scripts to avoid truncation
- Tab-complete the directory path instead of typing it
When it happens
Trigger: Passing `wmill flow preview` a path like `myfolder/` (no `.flow/__flow` suffix), a typo'd extension such as `flow.yml`, or a path to a non-flow file.
Common situations: Typing the directory manually instead of using the scaffolded `.flow/__flow` layout; using `.yml` instead of `.yaml`; passing a script path by mistake.
Related errors
- Cannot push flow ${remotePath}: step(s) reference non-worksp
- Step '${stepId}' not found in flow. Available steps: ${avail
- Resource ${remotePath} uses '!inline_fileset ${dirPath}', bu
- App ${appPath} not found
- Dependency generation failed: ${queueResponse.status} ${queu
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/47453ffcd5b2f827.
Report an issue: GitHub.