{"record":{"id":"63a4d05501cf61ae","repo":"windmill-labs/windmill","slug":"invalid-preprocessor-module-id-must-be-special","errorCode":null,"errorMessage":"Invalid preprocessor_module: id must be \"${SPECIAL_MODULE_IDS.PREPROCESSOR}\"","messagePattern":"Invalid preprocessor_module: id must be \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts","lineNumber":379,"sourceCode":"\t\tconst path = issue?.path?.join('.') ?? 'settings'\n\t\tthrow new Error(`Invalid flow setting ${path}: ${issue?.message ?? 'unknown error'}`)\n\t}\n\tconst settings = pickFlowValueSettings(settingsResult.data)\n\n\tconst modules = validateFlowModules(flow.modules, ctx)\n\tconst schema = validateFlowSchema(flow.schema)\n\tconst preprocessorModule = validateOptionalFlowModule(\n\t\tflow.preprocessor_module,\n\t\t'preprocessor_module'\n\t)\n\tconst failureModule = validateOptionalFlowModule(flow.failure_module, 'failure_module')\n\tconst groupModuleIds = new Set(collectAllFlowModuleIdsFromModules(modules))\n\tconst groups = validateFlowGroups(flow.groups, groupModuleIds)\n\tconst notes = validateFlowNotes(flow.notes, groupModuleIds)\n\n\tif (preprocessorModule) {\n\t\tif (preprocessorModule.id !== SPECIAL_MODULE_IDS.PREPROCESSOR) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid preprocessor_module: id must be \"${SPECIAL_MODULE_IDS.PREPROCESSOR}\"`\n\t\t\t)\n\t\t}\n\t\tif (\n\t\t\tpreprocessorModule.value.type !== 'rawscript' &&\n\t\t\tpreprocessorModule.value.type !== 'script'\n\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')","sourceCodeStart":361,"sourceCodeEnd":397,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts#L361-L397","documentation":"If a preprocessor_module is supplied, its `id` must be the reserved SPECIAL_MODULE_IDS.PREPROCESSOR value; the preprocessor is a distinguished module identified by that fixed id, not an arbitrary one. A differently-id'd module would not be recognized as the preprocessor by the backend, so the validator rejects it at edit time.","triggerScenarios":"Calling flowTools modules/patches with preprocessor_module whose id is e.g. \"prep\", \"preprocessor_1\", or a copied regular module id instead of the required SPECIAL_MODULE_IDS.PREPROCESSOR constant.","commonSituations":"An LLM invents an id for the preprocessor; a regular script module is moved into preprocessor_module without re-id'ing it; a template is edited and the id renamed.","solutions":["Set preprocessor_module.id to the exact required constant shown in the error message (SPECIAL_MODULE_IDS.PREPROCESSOR).","Re-run the tool after fixing the id.","Never reuse a regular module's id for the preprocessor."],"exampleFix":"// before\n{\"preprocessor_module\":{\"id\":\"prep\",...}}\n// after\n{\"preprocessor_module\":{\"id\":\"preprocessor\",...}}","handlingStrategy":"validation","validationCode":"import { SPECIAL_MODULE_IDS } from '../shared'\nif (flow.preprocessor_module && flow.preprocessor_module.id !== SPECIAL_MODULE_IDS.PREPROCESSOR)\n  throw new Error(`preprocessor_module.id must be ${SPECIAL_MODULE_IDS.PREPROCESSOR}`)","typeGuard":null,"tryCatchPattern":"try {\n  validateEditableFlowJson(raw)\n} catch (e) {\n  if (String(e.message).startsWith('Invalid preprocessor_module: id')) {\n    raw.preprocessor_module.id = SPECIAL_MODULE_IDS.PREPROCESSOR\n    return validateEditableFlowJson(raw)\n  }\n  throw e\n}","preventionTips":["Copy SPECIAL_MODULE_IDS.PREPROCESSOR into generated preprocessor modules","Never assign fresh UUIDs to special modules","Preserve the special id when moving a module into preprocessor_module"],"tags":["validation","flow-module","reserved-id"],"backgroundTag":"invalid-identifier-name","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"}