windmill-labs/windmill · error
Can only fork a script module
Error message
Can only fork a script module
What it means
fork converts a flow module into an inline editable script: it must fetch the script referenced by flowModule.value.path via createInlineScriptModuleFromPath. Forking only makes sense for modules whose value.type is 'script'; for hub/flow/while/branch/etc. modules there is no single script path to inline, so fork throws 'Can only fork a script module'.
Source
Thrown at frontend/src/lib/components/flows/flowStateUtils.svelte.ts:239
type: 'flow',
path: '',
input_transforms: {}
},
summary: ''
}
const flowModuleState = await loadFlowModuleState(flowFlowModules)
return [flowFlowModules, flowModuleState]
}
export async function fork(
flowModule: FlowModule,
// The acting workspace when the flow editor runs in an AI session; else the nav workspace.
workspace?: string
): Promise<[FlowModule & { value: RawScript }, FlowModuleState]> {
if (flowModule.value.type !== 'script') {
throw new Error('Can only fork a script module')
}
const forkedFlowModule = await createInlineScriptModuleFromPath(
flowModule.value.path ?? '',
flowModule.id,
workspace
)
const flowModuleState = await loadFlowModuleState(forkedFlowModule)
return [forkedFlowModule, flowModuleState]
}
async function createInlineScriptModuleFromPath(
path: string,
id: string,
workspace?: string
): Promise<FlowModule & { value: RawScript }> {
const { content, language } = await getScriptByPath(path, workspace)
return {View on GitHub (pinned to e474e8803c)
Solutions
- Check flowModule.value.type === 'script' before calling fork and hide/disable the fork action for other types.
- If forking whole flows, filter modules to script-type steps and skip/handle the rest explicitly.
- For non-script modules, use the appropriate conversion path (e.g. re-creating the step) instead of fork.
Example fix
// before const [mod, state] = await fork(flowModule) // after if (flowModule.value.type !== 'script') return const [mod, state] = await fork(flowModule)
Defensive patterns
Strategy: type-guard
Validate before calling
if (flowModule.value.type !== 'script') return
Type guard
function isScriptModule(m: FlowModule): m is FlowModule & { value: { type: 'script'; path?: string } } { return m.value.type === 'script' } Try / catch
try { await fork(fm) } catch (e) { if ((e as Error).message === 'Can only fork a script module') toast('Only script steps can be forked'); else throw e } Prevention
- Only render the fork/inline action for script-type modules.
- When batch-processing flows, branch on value.type before forking.
- Re-check type after any module-conversion operation (script <-> flow).
When it happens
Trigger: Calling fork(flowModule, workspace?) with a FlowModule whose value.type is not 'script' (e.g. a nested flow, hub item, loop, or raw-app step), typically from an 'inline/fork this step' UI action or custom tooling iterating over all modules.
Common situations: Batch-forking every module of a flow without filtering by type; attempting to inline a 'flow' or 'hub' step the UI shouldn't offer the action for; stale type info after a module was converted between kinds.
Related errors
- Failed to start test run - testFlow returned undefined
- No flow available to test step from. Please ensure you have
- Node ${moduleId} not found
- Cannot reject module without a beforeFlow snapshot
- Workspace '${forkWorkspaceId}' is not a fork (no parent_work
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/d61a03e778409ec5.
Report an issue: GitHub.