windmill-labs/windmill · error
Duplicate module ID found in failure_module: ${failureModule
Error message
Duplicate module ID found in failure_module: ${failureModule.id} What it means
validateEditableFlowJson rejects a failure_module whose id already exists among the flow's module IDs (including the preprocessor, which is added to the id set just before this check). IDs must be globally unique in a flow; duplicates would corrupt module references, so the error is thrown before anything is saved.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts:409
}
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
}
}
/**
* Build the agent-facing compact view of a flow. When an `InlineScriptSession`
* is provided, every rawscript module's `content` is moved into the session
* and replaced with the placeholder `inline_script.<moduleId>` (preprocessor
* and failure modules included).View on GitHub (pinned to e474e8803c)
Solutions
- Set failure_module.id to the reserved special id (SPECIAL_MODULE_IDS.FAILURE, i.e. 'failure') only if not already taken; otherwise pick a unique id
- Rename the colliding main-module id instead if references depend on it
- Regenerate with unique ids via the copilot tooling
Example fix
// before
modules: [{ id: 'failure', value: {...} }]
failure_module: { id: 'failure', ... }
// after
modules: [{ id: 'step1', value: {...} }]
failure_module: { id: 'failure', value: { type: 'rawscript', ... } } Defensive patterns
Strategy: validation
Validate before calling
const ids = new Set(collectAllFlowModuleIdsFromModules(modules))
if (preprocessor) ids.add(preprocessor.id)
if (failure && ids.has(failure.id)) throw new Error('duplicate failure id: ' + failure.id) Type guard
function failureIdIsUnique(modules, preprocessor, failure) {
const ids = new Set(collectAllFlowModuleIdsFromModules(modules))
if (preprocessor) ids.add(preprocessor.id)
return !failure || !ids.has(failure.id)
} Try / catch
try {
const editable = validateEditableFlowJson(json)
} catch (e) {
if (e.message.includes('Duplicate module ID found in failure_module')) {
delete json.failure_module // or rename the colliding module id
return validateEditableFlowJson(json)
}
throw e
} Prevention
- Reserve the id 'failure' exclusively for the failure module
- Assert global id uniqueness (modules + preprocessor + failure) before validating
- Regenerate ids when merging or copying flow JSON from another flow
When it happens
Trigger: Calling validateEditableFlowJson when failureModule.id matches any id in the modules array or the preprocessor_module id, e.g. two modules both id'd 'failure' or reusing 'last_step'.
Common situations: LLM emitting failure_module with id 'failure' while a main module already uses that id; copying an existing module into failure_module without changing its id; manual JSON edits merging flows.
Related errors
- Duplicate module ID found in preprocessor_module: ${preproce
- 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/39bc243c9cd9ce58.
Report an issue: GitHub.