windmill-labs/windmill · error

Invalid preprocessor_module: id must be "${SPECIAL_MODULE_ID

Error message

Invalid preprocessor_module: id must be "${SPECIAL_MODULE_IDS.PREPROCESSOR}"

What it means

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.

Source

Thrown at frontend/src/lib/components/copilot/chat/flow/editableFlowJson.ts:379

		const path = issue?.path?.join('.') ?? 'settings'
		throw new Error(`Invalid flow setting ${path}: ${issue?.message ?? 'unknown error'}`)
	}
	const settings = pickFlowValueSettings(settingsResult.data)

	const modules = validateFlowModules(flow.modules, ctx)
	const schema = validateFlowSchema(flow.schema)
	const preprocessorModule = validateOptionalFlowModule(
		flow.preprocessor_module,
		'preprocessor_module'
	)
	const failureModule = validateOptionalFlowModule(flow.failure_module, 'failure_module')
	const groupModuleIds = new Set(collectAllFlowModuleIdsFromModules(modules))
	const groups = validateFlowGroups(flow.groups, groupModuleIds)
	const notes = validateFlowNotes(flow.notes, groupModuleIds)

	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')

View on GitHub (pinned to e474e8803c)

Solutions

  1. Set preprocessor_module.id to the exact required constant shown in the error message (SPECIAL_MODULE_IDS.PREPROCESSOR).
  2. Re-run the tool after fixing the id.
  3. Never reuse a regular module's id for the preprocessor.

Example fix

// before
{"preprocessor_module":{"id":"prep",...}}
// after
{"preprocessor_module":{"id":"preprocessor",...}}
Defensive patterns

Strategy: validation

Validate before calling

import { SPECIAL_MODULE_IDS } from '../shared'
if (flow.preprocessor_module && flow.preprocessor_module.id !== SPECIAL_MODULE_IDS.PREPROCESSOR)
  throw new Error(`preprocessor_module.id must be ${SPECIAL_MODULE_IDS.PREPROCESSOR}`)

Try / catch

try {
  validateEditableFlowJson(raw)
} catch (e) {
  if (String(e.message).startsWith('Invalid preprocessor_module: id')) {
    raw.preprocessor_module.id = SPECIAL_MODULE_IDS.PREPROCESSOR
    return validateEditableFlowJson(raw)
  }
  throw e
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/63a4d05501cf61ae. Report an issue: GitHub.