{"record":{"id":"37c60d9b09eba359","repo":"windmill-labs/windmill","slug":"duplicate-module-id-found-in-preprocessor-module","errorCode":null,"errorMessage":"Duplicate module ID found in preprocessor_module: ${preprocessorModule.id}","messagePattern":"Duplicate module ID found in preprocessor_module: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts","lineNumber":404,"sourceCode":"\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t'Invalid preprocessor_module: only \"rawscript\" and \"script\" modules are supported'\n\t\t\t)\n\t\t}\n\t}\n\tif (failureModule) {\n\t\tif (failureModule.id !== SPECIAL_MODULE_IDS.FAILURE) {\n\t\t\tthrow new Error(`Invalid failure_module: id must be \"${SPECIAL_MODULE_IDS.FAILURE}\"`)\n\t\t}\n\t\tif (failureModule.value.type !== 'rawscript' && failureModule.value.type !== 'script') {\n\t\t\tthrow new Error('Invalid failure_module: only \"rawscript\" and \"script\" modules are supported')\n\t\t}\n\t}\n\n\tconst ids = new Set(collectAllFlowModuleIdsFromModules(modules))\n\tif (preprocessorModule) {\n\t\tif (ids.has(preprocessorModule.id)) {\n\t\t\tthrow new Error(`Duplicate module ID found in preprocessor_module: ${preprocessorModule.id}`)\n\t\t}\n\t\tids.add(preprocessorModule.id)\n\t}\n\tif (failureModule && ids.has(failureModule.id)) {\n\t\tthrow new Error(`Duplicate module ID found in failure_module: ${failureModule.id}`)\n\t}\n\n\treturn {\n\t\tmodules,\n\t\tschema,\n\t\tpreprocessor_module: preprocessorModule,\n\t\tfailure_module: failureModule,\n\t\tgroups,\n\t\tnotes,\n\t\t...settings\n\t}\n}\n","sourceCodeStart":386,"sourceCodeEnd":422,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts#L386-L422","documentation":"validateEditableFlowJson collects all module IDs in the flow and rejects a preprocessor_module whose id collides with any existing module ID. Module IDs must be unique across the whole flow including special modules; a duplicate would make references (branches, group start/end, failure routing) ambiguous, so the validator throws before saving.","triggerScenarios":"Calling validateEditableFlowJson when preprocessorModule.id equals the id of any module already in the modules array (as found by collectAllFlowModuleIdsFromModules), e.g. both are 'pre' or reuse of a main-module id.","commonSituations":"LLM reusing a placeholder id like 'module1' for the preprocessor; copy-pasting a module into the preprocessor slot without renaming its id; template merging that concatenates two id sets.","solutions":["Rename preprocessor_module.id to a fresh unique id (e.g. 'preprocessor')","Rename the colliding module instead if other references point at the preprocessor id","Regenerate the flow JSON letting the tooling assign unique ids"],"exampleFix":"// before\n{ id: 'step1', value: {...} } // in modules\npreprocessor_module: { id: 'step1', value: {...} }\n// after\n{ id: 'step1', value: {...} }\npreprocessor_module: { id: 'preprocessor', value: {...} }","handlingStrategy":"validation","validationCode":"const ids = new Set(collectAllFlowModuleIdsFromModules(modules))\nif (preprocessor && ids.has(preprocessor.id)) throw new Error('duplicate preprocessor id: ' + preprocessor.id)","typeGuard":"function hasUniqueIds(modules, preprocessor) {\n  const ids = new Set(collectAllFlowModuleIdsFromModules(modules))\n  return !preprocessor || !ids.has(preprocessor.id)\n}","tryCatchPattern":"try {\n  const editable = validateEditableFlowJson(json)\n} catch (e) {\n  if (e.message.includes('Duplicate module ID found in preprocessor_module')) {\n    json.preprocessor_module.id = 'preprocessor'\n    return validateEditableFlowJson(json)\n  }\n  throw e\n}","preventionTips":["Give the preprocessor a dedicated id like 'preprocessor' distinct from all module ids","Never reuse placeholder ids such as 'module1' across slots","Check id uniqueness across all slots before writing the flow"],"tags":["validation","flow","duplicate-id"],"backgroundTag":"duplicate-identifier","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"}