windmill-labs/windmill · error
Duplicate module ID found in preprocessor_module: ${preproce
Error message
Duplicate module ID found in preprocessor_module: ${preprocessorModule.id} What it means
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.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts:404
) {
throw new Error(
'Invalid preprocessor_module: only "rawscript" and "script" modules are supported'
)
}
}
if (failureModule) {
if (failureModule.id !== SPECIAL_MODULE_IDS.FAILURE) {
throw new Error(`Invalid failure_module: id must be "${SPECIAL_MODULE_IDS.FAILURE}"`)
}
if (failureModule.value.type !== 'rawscript' && failureModule.value.type !== 'script') {
throw new Error('Invalid failure_module: only "rawscript" and "script" modules are supported')
}
}
const ids = new Set(collectAllFlowModuleIdsFromModules(modules))
if (preprocessorModule) {
if (ids.has(preprocessorModule.id)) {
throw new Error(`Duplicate module ID found in preprocessor_module: ${preprocessorModule.id}`)
}
ids.add(preprocessorModule.id)
}
if (failureModule && ids.has(failureModule.id)) {
throw new Error(`Duplicate module ID found in failure_module: ${failureModule.id}`)
}
return {
modules,
schema,
preprocessor_module: preprocessorModule,
failure_module: failureModule,
groups,
notes,
...settings
}
}
View on GitHub (pinned to e474e8803c)
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
Example fix
// before
{ id: 'step1', value: {...} } // in modules
preprocessor_module: { id: 'step1', value: {...} }
// after
{ id: 'step1', value: {...} }
preprocessor_module: { id: 'preprocessor', value: {...} } Defensive patterns
Strategy: validation
Validate before calling
const ids = new Set(collectAllFlowModuleIdsFromModules(modules))
if (preprocessor && ids.has(preprocessor.id)) throw new Error('duplicate preprocessor id: ' + preprocessor.id) Type guard
function hasUniqueIds(modules, preprocessor) {
const ids = new Set(collectAllFlowModuleIdsFromModules(modules))
return !preprocessor || !ids.has(preprocessor.id)
} Try / catch
try {
const editable = validateEditableFlowJson(json)
} catch (e) {
if (e.message.includes('Duplicate module ID found in preprocessor_module')) {
json.preprocessor_module.id = 'preprocessor'
return validateEditableFlowJson(json)
}
throw e
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Duplicate module ID found in failure_module: ${failureModule
- Cannot push flow ${remotePath}: step(s) reference non-worksp
- Module value is undefined for module ${module.id}
- Invalid AI agent provider configuration: ${errors.join('\n')
- Invalid ${field}:\n${errors.join('\n')}
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/37c60d9b09eba359.
Report an issue: GitHub.