windmill-labs/windmill · error
Invalid group at index ${index}: end_id must be a non-empty
Error message
Invalid group at index ${index}: end_id must be a non-empty string What it means
Thrown by validateFlowGroups, a validation helper for LLM-supplied flow-group tool arguments, when the group object at `index` has an `end_id` that is missing, not a string, or empty. The flow-edit tools need each group to reference an existing end step id; malformed model-produced payloads are rejected here before the draft is touched.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:105
): FlowGroup[] | null {
if (rawGroups == null) {
return null
}
if (!Array.isArray(rawGroups)) {
throw new Error('Flow groups must be an array')
}
return rawGroups.map((group, index) => {
if (!group || typeof group !== 'object' || Array.isArray(group)) {
throw new Error(`Invalid group at index ${index}: must be an object`)
}
const g = group as Record<string, unknown>
if (typeof g.start_id !== 'string' || !g.start_id) {
throw new Error(`Invalid group at index ${index}: start_id must be a non-empty string`)
}
if (typeof g.end_id !== 'string' || !g.end_id) {
throw new Error(`Invalid group at index ${index}: end_id must be a non-empty string`)
}
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(', ')}`
)View on GitHub (pinned to e474e8803c)
Solutions
- Set end_id to the string id of the module where the group should end
- For a single-module group, set end_id equal to start_id
- Remove the group if not needed
Example fix
// before
groups: [{ start_id: 'a', end_id: '' }]
// after
groups: [{ start_id: 'a', end_id: 'b' }] Defensive patterns
Strategy: validation
Validate before calling
for (const [i, g] of (groups ?? []).entries()) {
if (typeof g.end_id !== 'string' || !g.end_id)
throw new Error(`groups[${i}].end_id must be a non-empty string`)
} Type guard
function hasValidEndId(g) {
return typeof g?.end_id === 'string' && g.end_id.length > 0
} Try / catch
try {
const groups = validateFlowGroups(raw, moduleIds)
} catch (e) {
if (e.message.includes('end_id must be a non-empty string')) {
const idx = Number(e.message.match(/index (\d+)/)?.[1])
raw[idx].end_id = raw[idx].start_id // single-module group fallback
return validateFlowGroups(raw, moduleIds)
}
throw e
} Prevention
- Include end_id in every group object, even single-module groups
- Let the LLM schema require end_id so omission fails at generation time
- Validate groups immediately after construction to catch missing fields early
When it happens
Trigger: Calling validateFlowGroups with a group object missing end_id, end_id: "", or a non-string end_id value.
Common situations: LLM truncating the group object; single-module group intended but written with only start_id and an empty end_id; placeholder not substituted.
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
- Invalid group at index ${index}: start_id must be a non-empt
- Flow groups must be an array
- Invalid group at index ${index}: must be an object
- Invalid group at index ${index}: start_id "${g.start_id}" do
- Invalid group at index ${index}: end_id "${g.end_id}" does n
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/c5be87d02ef3cfca.
Report an issue: GitHub.