windmill-labs/windmill · error · Error
Draft flow "${path}" has no value.
Error message
Draft flow "${path}" has no value. What it means
When reading a flow draft, the code expects the draft's value to be a structured FlowDraftValue object. If the draft exists but its value is undefined or only a string, it cannot produce a usable flow representation, so it throws. This keeps the model from treating a placeholder or serialized draft as a real flow value.
Source
Thrown at frontend/src/lib/components/copilot/chat/global/core.ts:5158
return writeScriptDraft(
{
path,
summary: base.summary,
language: base.language,
content: updated
},
ctx
)
}
async function loadFlowDraftValue(
path: string,
workspace: string
): Promise<{ flow: FlowDraftValue; summary?: string }> {
const draft = await getGlobalDraft(workspace, 'flow', path)
if (draft) {
if (draft.value === undefined || typeof draft.value === 'string') {
throw new Error(`Draft flow "${path}" has no value.`)
}
return { flow: draft.value as FlowDraftValue, summary: draft.summary }
}
const flow = await FlowService.getFlowByPath({ workspace, path })
return {
flow: { value: flow.value, schema: flow.schema, groups: flow.value.groups ?? null },
summary: flow.summary
}
}
/**
* `write_flow` accepts `inline_script.<id>` placeholders so the model can
* overwrite a flow without re-sending (or even reading) unchanged rawscript
* bodies. Resolve them against the current draft/deployed flow: an id with a
* stored body keeps it, a new module's own-id placeholder becomes an empty body
* (to fill via set_flow_module_code), and anything else rejects the write.
*/
async function resolveWriteFlowInlineScripts(View on GitHub (pinned to e474e8803c)
Solutions
- Delete the corrupted/empty flow draft and read again so it falls back to the deployed flow.
- Re-run write_flow with a complete flow value to overwrite the draft.
- Use patch_flow_json only after a valid draft or deployed flow exists.
Example fix
// before
draftStore.set(workspace, 'flow', path, { value: JSON.stringify(flow) }) // string value rejected
// after
draftStore.set(workspace, 'flow', path, { value: flowValue }) // structured FlowDraftValue Defensive patterns
Strategy: type-guard
Validate before calling
const draft = await getGlobalDraft(workspace, 'flow', path)
if (draft && (draft.value === undefined || typeof draft.value === 'string')) {
await deleteGlobalDraft(workspace, 'flow', path) // fall back to deployed flow
} Type guard
function isFlowDraftValue(v: unknown): v is FlowDraftValue {
return !!v && typeof v === 'object' && !Array.isArray(v) && 'value' in (v as object)
} Try / catch
try {
const { flow } = await readFlow(path)
} catch (e) {
if (String(e.message).includes('has no value')) {
await deleteDraft('flow', path)
const flow = await FlowService.getFlowByPath({ workspace, path })
} else throw e
} Prevention
- Write flow drafts only with a complete structured value, never raw JSON strings.
- After any interrupted write_flow run, verify or delete the draft.
- Keep one draft format; migrate old string-valued drafts before reading.
When it happens
Trigger: getGlobalDraft(workspace, 'flow', path) returns a draft with `value === undefined` or a string value — e.g. a flow draft created without a value payload or with a stale string body.
Common situations: A write_flow call was interrupted after registering the draft but before writing the value; an older draft format stored the flow as a JSON string that the new reader no longer accepts; a flow draft was created for a path but value construction failed upstream.
Related errors
- Draft script "${path}" is missing content or language.
- Draft script "${moduleValue.path}" is missing content or lan
- "${args.value}" is not a valid value for variable "${args.pa
- Invalid JSON after replacement: ${message}
- Module "${args.module_id}" is not an inline rawscript in flo
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/208af2d985acd68a.
Report an issue: GitHub.