windmill-labs/windmill · error · Error
Invalid group at index ${index}: end_id "${g.end_id}" does n
Error message
Invalid group at index ${index}: end_id "${g.end_id}" does not match any flow module What it means
validateFlowGroups checks that each group's end_id references an existing flow module when a moduleIds set is provided. This error is thrown when end_id does not match any module. It prevents a group box whose end boundary points at a non-existent node on the flow canvas.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:124
}
if (moduleIds) {
if (!moduleIds.has(g.start_id)) {
throw new Error(
`Invalid group at index ${index}: start_id "${g.start_id}" does not match any flow module`
)
}
if (!moduleIds.has(g.end_id)) {
throw new Error(
`Invalid group at index ${index}: end_id "${g.end_id}" does not match any flow module`
)
}
}
if (g.color !== undefined && g.color !== null) {
if (typeof g.color !== 'string' || !ALLOWED_NOTE_COLORS.has(g.color)) {
throw new Error(
`Invalid group at index ${index}: color must be one of ${[...ALLOWED_NOTE_COLORS].join(', ')}`
)
}
}
return g as unknown as FlowGroup
})
}
/**
* Validate the optional array of sticky notes the agent attached to the flow.
* Notes are editor-only annotations and do not affect execution.
*
* `free` notes are the supported kind (standalone canvas annotations). The
* `group` note type is deprecated for creation — the chat prompt steers the
* agent toward `groups` instead — but it is still ACCEPTED here so flows that
* already contain group notes round-trip cleanly through `patch_flow_json` /
* `set_flow_json` rather than being rejected. When `moduleIds` is provided,
* every `contained_node_ids` entry of a `group` note must reference an existing
* module.
*
* A provided palette `color` is always preserved as-is; the default is onlyView on GitHub (pinned to e474e8803c)
Solutions
- Use the exact `id` of an existing module from the flow value for end_id
- Re-read the current flow JSON to confirm module ids before writing groups
- Ensure the target end module exists in the same update if the group is meant to wrap a newly added module
- Remove or correct the group at the reported index
Example fix
// before
groups: [{ start_id: 'a1b2', end_id: 'last_step' }]
// after
groups: [{ start_id: 'a1b2', end_id: flow.value.modules[flow.value.modules.length - 1].id }] Defensive patterns
Strategy: validation
Validate before calling
const moduleIds = new Set(flow.value.modules.map((m) => m.id));
for (const [i, g] of (groups ?? []).entries()) {
if (!moduleIds.has(g.end_id)) throw new Error(`groups[${i}].end_id "${g.end_id}" is not a flow module id`);
} Type guard
function isValidGroupId(id: unknown, moduleIds: Set<string>): id is string {
return typeof id === 'string' && moduleIds.has(id);
} Try / catch
try {
validateFlowGroups(rawGroups, moduleIds);
} catch (e) {
if (e instanceof Error && /end_id .* does not match/.test(e.message)) {
console.error('Group end_id unknown — re-fetch flow JSON and retry with real ids');
} else throw e;
} Prevention
- Check both start_id and end_id against the module id set before submitting
- Take the end module id from the actual last module of the intended range
- Re-read the flow after prior edits, since earlier updates may have removed modules
When it happens
Trigger: patch_flow_json / set_flow_json called with groups where g.end_id (e.g. 'mod_final') is not a key in the moduleIds set built from the flow's modules — typically a hallucinated or stale id.
Common situations: LLM agent copies a start_id correctly but invents the end_id; the end module was removed by a previous tool call in the same session; ids were truncated or reformatted by the model.
Related errors
- Invalid group at index ${index}: start_id "${g.start_id}" do
- Flow groups must be an array
- Invalid group at index ${index}: must be an object
- Invalid group at index ${index}: start_id must be a non-empt
- Invalid group at index ${index}: end_id must be a non-empty
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/30f36337cb49c09d.
Report an issue: GitHub.