windmill-labs/windmill · error
Invalid ${field}: id must be "${expectedId}"
Error message
Invalid ${field}: id must be "${expectedId}" What it means
After schema validation succeeds, validateSpecialFlowModule additionally requires the module's id to equal the fixed expected id for that special field (specialFlowModuleFields[field]). A mismatch throws 'Invalid <field>: id must be "<expectedId>"'.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/core.ts:274
field: SpecialFlowModuleField
): FlowModule | null | undefined {
if (module === undefined || module === null) {
return module
}
const result = flowModuleSchema.safeParse(module)
if (!result.success) {
const errors = result.error.issues.slice(0, 5).map((issue) => {
const path = issue.path.length > 0 ? issue.path.join('.') : field
return `${path}: ${issue.message}`
})
throw new Error(`Invalid ${field}:\n${errors.join('\n')}`)
}
const parsedModule = result.data
const expectedId = specialFlowModuleFields[field]
if (parsedModule.id !== expectedId) {
throw new Error(`Invalid ${field}: id must be "${expectedId}"`)
}
if (parsedModule.value.type !== 'rawscript' && parsedModule.value.type !== 'script') {
throw new Error(`Invalid ${field}: only "rawscript" and "script" modules are supported`)
}
return parsedModule
}
const patchFlowJsonSchema = z.object({
old_string: z.string().min(1).describe('Exact text to find in the current compact flow JSON'),
new_string: z.string().describe('Replacement JSON text'),
replace_all: z
.boolean()
.optional()
.default(false)
.describe(
'When true, replace every exact match. When false, the search text must match exactly once.'View on GitHub (pinned to e474e8803c)
Solutions
- Set the module's id to the exact expected value reported in the error message.
- Ensure you are supplying the module to the correct special field (each field has its own expected id).
- Regenerate the flow JSON with the instruction that special modules use fixed sentinel ids.
Example fix
// before
{ "id": "approve_step", "value": ... }
// after
{ "id": "approval", "value": ... } Defensive patterns
Strategy: validation
Validate before calling
const expectedId = specialFlowModuleFields[field]
if (module.id !== expectedId) {
module = { ...module, id: expectedId }
} Type guard
function hasExpectedSpecialId(field: SpecialFlowModuleField, m: { id: string }): boolean {
return m.id === specialFlowModuleFields[field]
} Try / catch
try {
await tool.updateSpecialModule(field, module)
} catch (e) {
const m = e.message.match(/id must be "(.+)"/)
if (m) return tool.updateSpecialModule(field, { ...module, id: m[1] })
throw e
} Prevention
- Hard-code the sentinel id when constructing special modules; never derive it from user input.
- Normalize model-generated ids to the expected sentinel before validating.
- Consult specialFlowModuleFields when wiring a special field to its module.
When it happens
Trigger: The parsed module is structurally valid but parsedModule.id !== specialFlowModuleFields[field] — e.g. an id like 'my_step' or a duplicate/renamed id where the fixed sentinel id is required.
Common situations: Model invented a custom id for the special module; the module was copied from another flow and its id was edited; the caller passed the module into the wrong special field.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- 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')}
- Invalid ${field}: only "rawscript" and "script" modules are
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/556654fd0bbb5717.
Report an issue: GitHub.