windmill-labs/windmill · error
Invalid failure_module: id must be
Error message
Invalid failure_module: id must be "${SPECIAL_MODULE_IDS.FAILURE}" What it means
If a failure_module is supplied, its `id` must be the reserved SPECIAL_MODULE_IDS.FAILURE value; the failure handler is a distinguished module identified by that fixed id. Any other id would not be recognized as the failure handler by the backend, so it is rejected at edit time.
Solutions
- Set failure_module.id to the exact required constant shown in the error message (SPECIAL_MODULE_IDS.FAILURE).
- Ensure failure_module.value.type is "rawscript" or "script" (a sibling check throws otherwise).
- Re-run the tool after fixing the id.
Example fix
// before
{"failure_module":{"id":"on_failure",...}}
// after
{"failure_module":{"id":"failure",...}} Defensive patterns
Strategy: validation
Validate before calling
import { SPECIAL_MODULE_IDS } from '../shared'
if (flow.failure_module && flow.failure_module.id !== SPECIAL_MODULE_IDS.FAILURE)
throw new Error(`failure_module.id must be ${SPECIAL_MODULE_IDS.FAILURE}`) Try / catch
try {
validateEditableFlowJson(raw)
} catch (e) {
if (String(e.message).startsWith('Invalid failure_module: id')) {
raw.failure_module.id = SPECIAL_MODULE_IDS.FAILURE
return validateEditableFlowJson(raw)
}
throw e
} Prevention
- Copy SPECIAL_MODULE_IDS.FAILURE into generated failure modules
- Never assign fresh UUIDs to special modules
- Preserve the special id when moving a module into failure_module
When it happens
Trigger: Calling flowTools modules/patches with failure_module whose id is e.g. "failure_handler", "on_failure", or a copied regular module id instead of SPECIAL_MODULE_IDS.FAILURE.
Common situations: An LLM invents a descriptive id for the failure module; a regular error-handling script is moved into failure_module without re-id'ing it; renaming during a template edit.
Related errors
- Invalid preprocessor_module: id must be
- Invalid
- Invalid preprocessor_module: only "rawscript" and "script"…
- AI agent modules "`).join(', ')} need a provider input…
- An app already exists at
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/8c380a73f500e7ef.
Report an issue: GitHub.
Appendix: source
Thrown at frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts:394
if (preprocessorModule) {
if (preprocessorModule.id !== SPECIAL_MODULE_IDS.PREPROCESSOR) {
throw new Error(
`Invalid preprocessor_module: id must be "${SPECIAL_MODULE_IDS.PREPROCESSOR}"`
)
}
if (
preprocessorModule.value.type !== 'rawscript' &&
preprocessorModule.value.type !== 'script'
) {
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 {View on GitHub (pinned to e474e8803c)