windmill-labs/windmill · error
step '{}' references '{}', which is not a workspace path (ex
Error message
step '{}' references '{}', which is not a workspace path (expected u/, f/, g/ or hub/). Absolute or local filesystem paths are not allowed in flow steps. What it means
Flow validation enforces that script and flow module paths reference workspace runnables (paths starting with u/, f/, g/ or hub/). Absolute paths like /home/user/x.py or local filesystem references are rejected because the engine can only resolve workspace-hosted code, preventing accidental or unsafe local-path references.
Source
Thrown at backend/windmill-types/src/flows.rs:250
fn validate_flow_value<'de, D>(deserializer: D) -> Result<Box<RawValue>, D::Error>
where
D: Deserializer<'de>,
{
let raw_value = Box::<RawValue>::deserialize(deserializer)?;
let flow_value: FlowValue = serde_json::from_str(raw_value.get())
.map_err(|e| serde::de::Error::custom(format!("Invalid flow value: {}", e)))?;
let mut validate_module = |module: &FlowModule| -> anyhow::Result<()> {
if let Some(ref retry) = module.retry {
validate_retry(retry, &module.id)?;
}
if let Ok(FlowModuleValue::Script { path, .. } | FlowModuleValue::Flow { path, .. }) =
module.get_value()
{
if !is_workspace_runnable_path(&path) {
return Err(anyhow::anyhow!(
"step '{}' references '{}', which is not a workspace path (expected u/, \
f/, g/ or hub/). Absolute or local filesystem paths are not allowed in \
flow steps.",
module.id,
path
));
}
}
Ok(())
};
// The API is the authoritative guard (it can be called directly, bypassing the CLI), so
// it must cover every step that resolves a path: the main modules AND the failure /
// preprocessor modules (which can themselves be sub-flows/loops/branches).
let extra_modules: Vec<FlowModule> = flow_value
.failure_module
.iter()
.chain(flow_value.preprocessor_module.iter())View on GitHub (pinned to e474e8803c)
Solutions
- Prefix the path correctly: 'u/<user>/<script>' for user scripts, 'f/<folder>/<script>' for folder scripts, or 'hub/...' for hub scripts
- Upload the local script to the workspace first, then reference its workspace path in the module
- Fix the module path in the flow editor and re-save
Example fix
// before
{"type": "script", "path": "/home/me/etl.py"}
// after
{"type": "script", "path": "u/me/etl"} Defensive patterns
Strategy: validation
Validate before calling
function isWorkspaceRunnablePath(p) {
return /^(u|f|g|hub)\//.test(p);
}
// before saving: flow.modules.forEach(m => {
// if ((m.value.type === "script" || m.value.type === "flow") && !isWorkspaceRunnablePath(m.value.path))
// throw new Error(`module ${m.id}: path ${m.value.path} is not a workspace path`);
// }); Prevention
- Upload local scripts to the workspace first, then reference them by workspace path
- Never paste local/absolute filesystem paths into flow step configs
- Lint generated flow JSON for path prefixes before deploy
When it happens
Trigger: Saving a flow where a Script or Flow module's `path` is e.g. '/scripts/foo.py', 'file://...', or a bare name without a workspace prefix — caught by validate_flow_value on create/update.
Common situations: Migrating scripts from local directories into flows, copying paths from CLI invocations of local files, typos omitting the u/ or f/ prefix, or generated flows from AI/tooling that emit raw file paths.
Related errors
- Cannot push flow ${remotePath}: step(s) reference non-worksp
- Module "${args.module_id}" is not an inline rawscript in flo
- Module "${args.module_id}" is not an inline rawscript in flo
- Failed to parse flow value: {}
- Module '{}': Exponential backoff base (seconds) must be grea
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/9522e74d4f160fd4.
Report an issue: GitHub.