windmill-labs/windmill · error
Invalid group at index ${index}: must be an object
Error message
Invalid group at index ${index}: must be an object What it means
Each entry of the flow groups array must be a plain object describing a note box (start_id, end_id, optional summary/color). validateFlowGroups rejects null, non-object, or array elements at the given index so downstream code can safely read group fields.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:98
rawScriptModule.value.content = code
return rawScriptModule
}
export function validateFlowGroups(
rawGroups: unknown,
moduleIds?: Set<string>
): 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`
)View on GitHub (pinned to e474e8803c)
Solutions
- Replace the invalid element with a group object: { start_id: '<module id>', end_id: '<module id>' }
- Remove the null/primitive entry from the array
- If ids-only was intended, restructure as objects with start_id/end_id
Example fix
// before
groups: ['a', 'b']
// after
groups: [{ start_id: 'a', end_id: 'b' }] Defensive patterns
Strategy: type-guard
Validate before calling
const bad = (groups ?? []).findIndex(g => g == null || typeof g !== 'object' || Array.isArray(g))
if (bad !== -1) throw new Error(`groups[${bad}] must be an object`) Type guard
function isFlowGroup(g) {
return typeof g === 'object' && g !== null && !Array.isArray(g)
} Try / catch
try {
const groups = validateFlowGroups(raw, moduleIds)
} catch (e) {
if (e.message.includes('must be an object')) {
const idx = Number(e.message.match(/index (\d+)/)?.[1])
sanitized.splice(idx, 1) // drop the bad entry and retry
return validateFlowGroups(sanitized, moduleIds)
}
throw e
} Prevention
- Filter out null/undefined entries before validating groups
- Never pass raw id lists as groups; always build { start_id, end_id } objects
- Validate each group object individually when constructing it
When it happens
Trigger: Calling validateFlowGroups with an array containing null, a primitive (e.g. 'group1', 42), or a nested array at that index — e.g. groups: [null] or groups: [['a','b']].
Common situations: LLM emitting a list of id pairs instead of group objects; JSON with empty slots; mapping over module ids directly and passing the result as groups.
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
- Flow groups must be an array
- result.substring(__RESULT_ERR_PREFIX.length)
- Flow modules must be an array
- 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/7414a67ad4521f1d.
Report an issue: GitHub.