{"record":{"id":"ea8901c5632d1771","repo":"windmill-labs/windmill","slug":"duplicate-module-ids-found-in-flow","errorCode":null,"errorMessage":"Duplicate module IDs found in flow","messagePattern":"Duplicate module IDs found in flow","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/flow/core.ts","lineNumber":766,"sourceCode":"\t\t\t\tconst effectiveModules =\n\t\t\t\t\tparsedModules ?? helpers.getFlowAndSelectedId().flow.value.modules ?? []\n\t\t\t\tconst moduleIdsForGroups = new Set(collectAllFlowModuleIdsFromModules(effectiveModules))\n\t\t\t\tif (parsedGroups !== undefined) {\n\t\t\t\t\tparsedGroups = validateFlowGroups(parsedGroups, moduleIdsForGroups)\n\t\t\t\t}\n\t\t\t\tif (parsedNotes !== undefined) {\n\t\t\t\t\tparsedNotes = validateFlowNotes(parsedNotes, moduleIdsForGroups)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst ids = [\n\t\t\t\t...(parsedModules ? collectAllFlowModuleIdsFromModules(parsedModules) : []),\n\t\t\t\t...[parsedPreprocessorModule, parsedFailureModule]\n\t\t\t\t\t.filter((module): module is FlowModule => module !== undefined && module !== null)\n\t\t\t\t\t.map((module) => module.id)\n\t\t\t]\n\t\t\tif (ids.length !== new Set(ids).size) {\n\t\t\t\tthrow new Error('Duplicate module IDs found in flow')\n\t\t\t}\n\n\t\t\ttoolCallbacks.setToolStatus(toolId, {\n\t\t\t\tcontent: `Setting flow...`\n\t\t\t})\n\t\t\tconst updateResult = await helpers.setFlowJson({\n\t\t\t\t...(parsedModules !== undefined ? { modules: parsedModules } : {}),\n\t\t\t\t...(parsedSchema !== undefined ? { schema: parsedSchema } : {}),\n\t\t\t\t...(parsedPreprocessorModule !== undefined\n\t\t\t\t\t? { preprocessorModule: parsedPreprocessorModule }\n\t\t\t\t\t: {}),\n\t\t\t\t...(parsedFailureModule !== undefined ? { failureModule: parsedFailureModule } : {}),\n\t\t\t\t...(parsedGroups !== undefined ? { groups: parsedGroups } : {}),\n\t\t\t\t...(parsedNotes !== undefined ? { notes: parsedNotes } : {})\n\t\t\t})\n\t\t\tconst warning = formatEmptyInlineScriptWarning(updateResult)\n\n\t\t\t// Update exprsToSet if the selected module has input_transforms","sourceCodeStart":748,"sourceCodeEnd":784,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/flow/core.ts#L748-L784","documentation":"The set-flow tool collects every module ID from the modules array plus the preprocessor and failure modules and rejects the payload if any ID appears twice. Duplicate IDs would make the flow graph ambiguous (edges and step references could not be resolved uniquely), so the tool fails fast before writing anything to the editor.","triggerScenarios":"set_flow where the same module id appears in two entries of modules, or the same id is used both inside modules and as preprocessor_module/failure_module.","commonSituations":"The model duplicates a step when regenerating the flow (copy/paste of a branch without renaming IDs); a template payload was appended to an existing modules list without ID renaming; a special module was accidentally duplicated in both a dedicated field and modules.","solutions":["Assign a fresh unique ID to the duplicated module (or remove the redundant copy) and resubmit.","Check that preprocessor_module/failure_module IDs don't also appear in the modules array.","List all IDs first (collect them from the payload) and de-duplicate before calling set_flow.","When copying a branch/step, always rename the copied module's ID to a new unique value."],"exampleFix":"// before: duplicate id\nsetFlow({ modules: [{ id: 'step1', ... }, { id: 'step1', ... }] })\n// after\nsetFlow({ modules: [{ id: 'step1', ... }, { id: 'step2', ... }] })","handlingStrategy":"validation","validationCode":"const ids = modules.map((m) => m.id)\nif (new Set(ids).size !== ids.length) throw new Error('De-duplicate module IDs before calling set_flow')","typeGuard":"function hasUniqueIds(modules: { id: string }[]): boolean {\n  return new Set(modules.map((m) => m.id)).size === modules.length\n}","tryCatchPattern":"try {\n  await setFlow(payload)\n} catch (e) {\n  if (e.message === 'Duplicate module IDs found in flow') {\n    const fixed = renameDuplicateIds(payload)\n    await setFlow(fixed)\n  } else throw e\n}","preventionTips":["Rename IDs whenever copying or templating a step or branch","Check the dedicated preprocessor/failure fields against modules[] IDs too","Run a uniqueness pass over the payload before submitting"],"tags":["copilot","flow-validation","duplicate-ids"],"backgroundTag":"duplicate-module-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"}