{"record":{"id":"c093d4f9c9dfbeff","repo":"windmill-labs/windmill","slug":"node-moduleid-not-found","errorCode":null,"errorMessage":"Node ${moduleId} not found","messagePattern":"Node (.+?) not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/flows/branchOps.ts","lineNumber":22,"sourceCode":"import type { StateStore } from '$lib/utils'\nimport type { History } from '$lib/history.svelte'\nimport { push } from '$lib/history.svelte'\nimport { dfs } from './dfs'\nimport { findModuleInFlow } from './flowTree'\n\ntype BranchList = Array<{ summary?: string; expr?: string; modules: FlowModule[] }>\n\ntype Ctx = {\n\tflowStore: StateStore<ExtendedOpenFlow>\n\tflowStateStore: StateStore<FlowState>\n\thistory: History<ExtendedOpenFlow>\n}\n\n/** Append an empty branch to a branchone/branchall step. */\nexport function addBranch(moduleId: string, { flowStore, history }: Omit<Ctx, 'flowStateStore'>) {\n\tpush(history, flowStore.val)\n\tconst module = findModuleInFlow(flowStore.val.value, moduleId)\n\tif (!module) throw new Error(`Node ${moduleId} not found`)\n\n\tif (module.value.type === 'branchone' || module.value.type === 'branchall') {\n\t\tmodule.value.branches.push({ summary: '', expr: 'false', modules: [] })\n\t}\n}\n\n/**\n * Drop a branch and the flow state of every step inside it.\n *\n * `index` counts the way the graph lays the branches out, where a branchone's default\n * occupies slot 0 — one ahead of the same branch's position in `value.branches`. Callers\n * working from the array (the settings panel) must add that offset back.\n */\nexport function removeBranch(\n\tmoduleId: string,\n\tindex: number,\n\t{ flowStore, flowStateStore, history }: Ctx\n) {","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/flows/branchOps.ts#L4-L40","documentation":"addBranch appends an empty branch to a branchone/branchall step in the flow store. It locates the step by id via findModuleInFlow over the whole flow tree; if no module with that id exists it throws `Node ${moduleId} not found` (after already pushing an undo history entry). It indicates the target step id does not refer to any node currently in the flow.","triggerScenarios":"Calling addBranch(moduleId, ctx) with a stale/renamed/deleted module id, an id that includes a duplicate prefix (e.g. from the diff manager) that findModuleInFlow can't match, or an id belonging to a different flow than the one in flowStore.","commonSituations":"UI settings panel acting on a node that was just removed by another tab/collaborator (multiplayer); id normalization mismatches after copy/paste or import; dev code reusing cached ids across flow loads.","solutions":["Verify the moduleId exists in the current flow (findModuleInFlow / flow outline) before calling addBranch.","Strip any prefix from the id before lookup if the id came from a tracked action (see DUPLICATE_MODULE_PREFIX handling in flowDiffManager).","Re-fetch/reload the flow if it changed remotely, then retry with the fresh id.","If triggering from UI, capture the id at event time from the live module object rather than stale state."],"exampleFix":"// before\naddBranch(moduleId, ctx)\n// after\nimport { findModuleInFlow } from './flowTree'\nif (!findModuleInFlow($flowStore.val.value, moduleId)) return\naddBranch(moduleId, ctx)","handlingStrategy":"validation","validationCode":"import { findModuleInFlow } from './flowTree'\nif (!findModuleInFlow(flowStore.val.value, moduleId)) return // unknown node","typeGuard":"const module = findModuleInFlow(flow.val.value, moduleId)\nif (!module) return\nif (module.value.type !== 'branchone' && module.value.type !== 'branchall') return","tryCatchPattern":"try { addBranch(moduleId, ctx) } catch (e) { if (String((e as Error).message).startsWith('Node ')) reloadFlowAndNotify(); else throw e }","preventionTips":["Always look up ids from the current flow snapshot at action time.","Strip duplicate-action prefixes from ids before node lookup.","Re-resolve ids after undo/redo or remote (multiplayer) flow updates."],"tags":["flow-editor","branch","frontend","stale-state"],"backgroundTag":"node-not-found","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"}