windmill-labs/windmill · error
Node ${detail.id} not found
Error message
Node ${detail.id} not found What it means
In FlowModuleSchemaMap.svelte, the onUpdateMock handler receives an id from the map UI and looks up the corresponding flow module via findModuleById. If no module with that id exists in the flow, it throws 'Node ${id} not found'. This guards against stale or foreign node ids being applied to the flow store.
Source
Thrown at frontend/src/lib/components/flows/map/FlowModuleSchemaMap.svelte:937
clone.id = copyId(original.id, flowStateStore.val, flowStore.val)
flowStateStore.val[clone.id] = emptyFlowModuleState()
dfs([clone], (mod) => {
if (mod.id !== clone.id) {
const newModId = nextId(flowStateStore.val, flowStore.val)
mod.id = newModId
flowStateStore.val[newModId] = emptyFlowModuleState()
}
})
targetModules.splice(targetIndex + 1, 0, clone)
refreshFlowStateStore(flowStore)
selectionManager.selectId(clone.id, { openPanel: true })
}}
onUpdateMock={(detail) => {
let module = findModuleById(detail.id)
if (!module) {
throw new Error(`Node ${detail.id} not found`)
}
module.mock = $state.snapshot(detail.mock)
refreshFlowStateStore(flowStore)
}}
{onTestFlow}
{isRunning}
{onCancelTestFlow}
{onOpenPreview}
{onHideJobStatus}
{controlsPosition}
exitNoteMode={() => (noteMode = false)}
onNotePositionUpdate={(noteId, position) => {
// Update note position via NoteEditor context in edit mode
if (noteEditorContext?.noteEditor) {
noteEditorContext.noteEditor.updatePosition(noteId, position)
}
}}
multiSelectEnabledView on GitHub (pinned to e474e8803c)
Solutions
- Reload the flow/schema map so node ids match the current flow, then retry the mock update
- Verify the module id exists in the current flow (check value.modules in the YAML or the editor)
- Avoid editing mocks on a stale tab — refresh before continuing concurrent edits
- If it recurs, check for flow version mismatches (unsaved local copy vs server version)
Example fix
// before
onUpdateMock={(detail) => {
const module = findModuleById(detail.id)
module.mock = detail.mock
}}
// after
onUpdateMock={(detail) => {
const module = findModuleById(detail.id)
if (!module) {
sendUserToast('Module no longer exists — reloading flow', true)
return
}
module.mock = $state.snapshot(detail.mock)
}} Defensive patterns
Strategy: try-catch
Validate before calling
const module = findModuleById(detail.id)
if (!module) { console.warn('module gone, reloading flow'); await reloadFlow(); return } Type guard
function moduleExists(id: string): boolean {
return flowStore.get().value.modules.some(m => m.id === id)
} Try / catch
try {
updateMock(detail)
} catch (e) {
if (e.message.startsWith('Node ') && e.message.endsWith(' not found')) {
sendUserToast('Module no longer exists — refresh the flow', true)
await refreshFlow()
}
} Prevention
- Refresh the flow after any external modification before editing mocks
- Avoid multiple concurrent editors on the same flow
- Re-read flow state after save/reload cycles instead of caching module ids
- Handle delete events in the UI by clearing stale selections
When it happens
Trigger: Dispatching an update-mock event with a detail.id that no longer exists in the flow — e.g. the module was deleted in another tab/user session, the flow was reloaded and ids changed, or a stale selection was used.
Common situations: Two users editing the same flow concurrently (one deletes a module while another edits its mock); the schema map kept a cached node id across a flow reload; ids differ between draft and saved flow versions.
Related errors
- Failed to cache esbuild-wasm@${version} at ${destDir}
- Draft "${path}" changed externally since you last read it; i
- This draft has a newer conflicting version on the server. Re
- validationErrors.join('\n')
- The app preview is collapsed, so there is nothing to capture
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/5f4e0d894dc8e38f.
Report an issue: GitHub.