{"record":{"id":"30f36337cb49c09d","repo":"windmill-labs/windmill","slug":"invalid-group-at-index-index-end-id-g-end-i","errorCode":null,"errorMessage":"Invalid group at index ${index}: end_id \"${g.end_id}\" does not match any flow module","messagePattern":"Invalid group at index (.+?): end_id \"(.+?)\" does not match any flow module","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/copilot/chat/flow/helperUtils.ts","lineNumber":124,"sourceCode":"\t\t}\n\t\tif (moduleIds) {\n\t\t\tif (!moduleIds.has(g.start_id)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid group at index ${index}: start_id \"${g.start_id}\" does not match any flow module`\n\t\t\t\t)\n\t\t\t}\n\t\t\tif (!moduleIds.has(g.end_id)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid group at index ${index}: end_id \"${g.end_id}\" does not match any flow module`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\tif (g.color !== undefined && g.color !== null) {\n\t\t\tif (typeof g.color !== 'string' || !ALLOWED_NOTE_COLORS.has(g.color)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Invalid group at index ${index}: color must be one of ${[...ALLOWED_NOTE_COLORS].join(', ')}`\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\t\treturn g as unknown as FlowGroup\n\t})\n}\n\n/**\n * Validate the optional array of sticky notes the agent attached to the flow.\n * Notes are editor-only annotations and do not affect execution.\n *\n * `free` notes are the supported kind (standalone canvas annotations). The\n * `group` note type is deprecated for creation — the chat prompt steers the\n * agent toward `groups` instead — but it is still ACCEPTED here so flows that\n * already contain group notes round-trip cleanly through `patch_flow_json` /\n * `set_flow_json` rather than being rejected. When `moduleIds` is provided,\n * every `contained_node_ids` entry of a `group` note must reference an existing\n * module.\n *\n * A provided palette `color` is always preserved as-is; the default is only","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/copilot/chat/flow/helperUtils.ts#L106-L142","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ngroups: [{ start_id: 'a1b2', end_id: 'last_step' }]\n// after\ngroups: [{ start_id: 'a1b2', end_id: flow.value.modules[flow.value.modules.length - 1].id }]","handlingStrategy":"validation","validationCode":"const moduleIds = new Set(flow.value.modules.map((m) => m.id));\nfor (const [i, g] of (groups ?? []).entries()) {\n  if (!moduleIds.has(g.end_id)) throw new Error(`groups[${i}].end_id \"${g.end_id}\" is not a flow module id`);\n}","typeGuard":"function isValidGroupId(id: unknown, moduleIds: Set<string>): id is string {\n  return typeof id === 'string' && moduleIds.has(id);\n}","tryCatchPattern":"try {\n  validateFlowGroups(rawGroups, moduleIds);\n} catch (e) {\n  if (e instanceof Error && /end_id .* does not match/.test(e.message)) {\n    console.error('Group end_id unknown — re-fetch flow JSON and retry with real ids');\n  } else throw e;\n}","preventionTips":["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"],"tags":["validation","flow-groups","module-id","referential-integrity"],"backgroundTag":"unknown-referenced-id","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}