{"record":{"id":"acd29ba2a3bf15ca","repo":"windmill-labs/windmill","slug":"duplicated-node-detected-module-id","errorCode":null,"errorMessage":"Duplicated node detected: ${module.id}","messagePattern":"Duplicated node detected: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/graph/graphBuilder.svelte.ts","lineNumber":466,"sourceCode":"\ttry {\n\t\tif (!modules) {\n\t\t\treturn { nodes: {}, edges: [] }\n\t\t}\n\n\t\tconst nodes: NodeLayout[] = []\n\t\tconst edges: Edge[] = []\n\n\t\t// Lookup map from module ID to the original reactive FlowModule objects.\n\t\tconst moduleMap = new Map<string, FlowModule>()\n\t\tfor (const m of getAllModules(modules, failureModule)) {\n\t\t\tmoduleMap.set(m.id, m)\n\t\t}\n\n\t\tfunction addNode(module: FlowModule, extraData?: Record<string, any>) {\n\t\t\tconst duplicated = nodes.find((n) => n.id === module.id)\n\t\t\tif (duplicated) {\n\t\t\t\tconsole.log('Duplicated node detected: ', module, duplicated)\n\t\t\t\tthrow new Error(`Duplicated node detected: ${module.id}`)\n\t\t\t}\n\n\t\t\tnodes.push({\n\t\t\t\tid: module.id,\n\t\t\t\tdata: {\n\t\t\t\t\tmodule: module,\n\t\t\t\t\tid: module.id,\n\t\t\t\t\tparentIds: [],\n\t\t\t\t\teventHandlers: eventHandlers,\n\t\t\t\t\ttestModuleState: extra.testModuleStates?.states?.[module.id],\n\t\t\t\t\tinsertable: extra.insertable && !module.id.startsWith('subflow:'),\n\t\t\t\t\teditMode: extra.editMode,\n\t\t\t\t\tisOwner: extra.isOwner,\n\t\t\t\t\tassets: getFlowModuleAssets(module, extra.additionalAssetsMap),\n\t\t\t\t\tmoduleAction: extra.moduleActions?.[module.id],\n\t\t\t\t\t...extraData\n\t\t\t\t},\n\t\t\t\ttype: 'module',","sourceCodeStart":448,"sourceCodeEnd":484,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/graph/graphBuilder.svelte.ts#L448-L484","documentation":"graphBuilder's addNode refuses to insert two graph nodes with the same id, since React Flow requires unique node ids. A duplicate means the same FlowModule (same id) was encountered twice while walking the flow's modules.","triggerScenarios":"processModules (or addFailureNode) encounters two FlowModule entries with identical module.id — e.g. the flow JSON literally lists the same step id twice, or a branch/foreach expansion re-emits a step already added.","commonSituations":"Hand-edited or programmatically generated flow JSON reusing a step id; copy-paste of a branch in the editor that duplicated ids; a backend/plugin bug emitting a module in both the main list and a child list.","solutions":["Open the flow JSON and give each duplicated step a unique id, then redeploy.","In the editor, delete and re-add the duplicated step so it gets a fresh id.","If the flow was generated by a script, fix the generator to assign unique ids per step.","Check for accidental double-inclusion of child modules (branch/foreach inputs) and deduplicate."],"exampleFix":"// before\n[{ \"id\": \"step1\", ... }, { \"id\": \"step1\", ... }]\n// after\n[{ \"id\": \"step1\", ... }, { \"id\": \"step2\", ... }]","handlingStrategy":"validation","validationCode":"const seen = new Set()\nfor (const m of modules) { if (seen.has(m.id)) console.warn('duplicate module id', m.id); seen.add(m.id) }","typeGuard":"function hasUniqueIds(modules) { return new Set(modules.map(m => m.id)).size === modules.length }","tryCatchPattern":"try { buildGraph(flow) } catch (e) { if (String(e.message).startsWith('Duplicated node detected')) reloadFlowWithFreshIds(); else throw e }","preventionTips":["Regenerate ids when copying/duplicating steps or branches","Validate flow JSON uniqueness before deploying generated flows","Never hand-edit step ids without checking global uniqueness"],"tags":["graph","react-flow","duplicate-id"],"backgroundTag":"duplicate-node-id","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"}