{"record":{"id":"1d158cdc86c7ed56","repo":"windmill-labs/windmill","slug":"cannot-push-flow-remotepath-step-s-reference","errorCode":null,"errorMessage":"Cannot push flow ${remotePath}: step(s) reference non-workspace path(s): ${badStepPaths.join(\", \")}. Flow step paths must be workspace paths (u/, f/, g/ or hub/), not absolute or local filesystem paths. This usually means flow.yaml was generated with paths from a checkout directory.","messagePattern":"Cannot push flow (.+?): step\\(s\\) reference non-workspace path\\(s\\): (.+?)\\. Flow step paths must be workspace paths \\(u/, f/, g/ or hub/\\), not absolute or local filesystem paths\\. This usually means flow\\.yaml was generated with paths from a checkout directory\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cli/src/commands/flow/flow.ts","lineNumber":231,"sourceCode":"    // Hard-fail rather than push the literal `!inline path` text as\n    // rawscript.content. That string would be persisted in flow_version.value\n    // and round-trip as the script body on the next pull, overwriting the\n    // user's local handler with the directive — see GIT-871 / #9140.\n    throw new Error(\n      `Cannot push flow ${remotePath}: missing inline script file(s): ${missingFiles.join(\", \")}. ` +\n      `Either restore the file(s) or remove the !inline reference(s) from flow.yaml before pushing.`\n    );\n  }\n\n  // Reject script/sub-flow steps whose path is not a workspace path (u/, f/, g/ or hub/).\n  // A flow.yaml generated from a feature-branch checkout can carry absolute local paths\n  // (e.g. /tmp/.../ops/scripts/...); pushed, they silently mis-resolve at runtime (#9751).\n  // The backend re-validates the same rule for every step type, so this is a fail-fast.\n  const badStepPaths = collectStepPaths(localFlow.value).filter(\n    (p) => p !== \"\" && !/^(u|f|g|hub)\\//.test(p)\n  );\n  if (badStepPaths.length > 0) {\n    throw new Error(\n      `Cannot push flow ${remotePath}: step(s) reference non-workspace path(s): ${badStepPaths.join(\", \")}. ` +\n      `Flow step paths must be workspace paths (u/, f/, g/ or hub/), not absolute or local filesystem paths. ` +\n      `This usually means flow.yaml was generated with paths from a checkout directory.`\n    );\n  }\n\n  const hasOnBehalfOf = (localFlow as any).has_on_behalf_of ?? !!localFlow.on_behalf_of_email;\n  delete (localFlow as any).has_on_behalf_of;\n  // The authorization half of the identity is never exported to the repo (the\n  // workspace tarball strips it); it only ever travels back from the remote row.\n  delete (localFlow as any).on_behalf_of;\n\n  const preserveFields: {\n    on_behalf_of_email?: string;\n    on_behalf_of?: string;\n    preserve_on_behalf_of?: boolean;\n  } = {};\n  if (permissionedAsContext?.userIsAdminOrDeployer && hasOnBehalfOf) {","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/cli/src/commands/flow/flow.ts#L213-L249","documentation":"`wmill flow push` validates that every step path in the flow is a workspace path (u/, f/, g/ or hub/ prefixed). If `collectStepPaths` finds absolute or local filesystem paths (e.g. /tmp/.../ops/scripts/...), it throws this fail-fast error, because such steps would silently mis-resolve at runtime; the backend re-validates the same rule (#9751).","triggerScenarios":"Pushing a flow.yaml generated with local checkout paths embedded in step path fields — typically from AI generation or tooling that wrote absolute paths from the machine's checkout directory instead of workspace paths.","commonSituations":"Flows scaffolded by scripts/agents that pasted filesystem paths; copying flow.yaml between machines; editing flow.yaml by hand with absolute paths; flows exported from another system.","solutions":["Edit flow.yaml and replace each listed path with a workspace path (u/user/..., f/folder/..., g/..., or hub/...).","Re-generate the flow with tooling configured to emit workspace-relative paths.","Pre-create referenced scripts in the workspace and reference them by their workspace path."],"exampleFix":"// before (flow.yaml)\npath: /tmp/checkout/ops/scripts/notify.ts\n// after\npath: u/admin/notify","handlingStrategy":"validation","validationCode":"const WS_PATH = /^(u|f|g|hub)\\//;\nconst bad = stepPaths(flow).filter(p => p !== '' && !WS_PATH.test(p));\nif (bad.length) throw new Error('non-workspace step paths: ' + bad.join(', '));","typeGuard":"function isWorkspacePath(p: string): boolean { return /^(u|f|g|hub)\\//.test(p); }","tryCatchPattern":"try { await pushFlow(...) } catch (e) { if (String(e).includes('non-workspace path')) rewriteStepPathsToWorkspace(flowYaml); else throw e; }","preventionTips":["Generate flows with workspace paths, never absolute filesystem paths","Validate flow.yaml paths in CI before pushing","Pre-create referenced scripts and use their u/, f/ or g/ paths","Review AI/tool-generated flow.yaml for checkout-directory leakage before push"],"tags":["cli","flow","validation","path-validation"],"backgroundTag":"invalid-workspace-path","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}