windmill-labs/windmill · error
Group(s) ${ids} could not be resolved: their start/end nodes
Error message
Group(s) ${ids} could not be resolved: their start/end nodes do not belong to the same branch What it means
buildStructureTree converts flat flow modules plus GraphGroups (branch groupings) into a nested flow structure tree. After recursion, any group that was not consumed by buildStructureTreeRecurse could not be matched to a branch — its start_id and end_id don't sit within the same branch — so it throws with the offending group ids listed.
Source
Thrown at frontend/src/lib/components/graph/flowStructure.ts:43
moduleIds?: string[]
/** Child branches. leaf=[], group=[{children}], container=[{children}, ...] */
branches: StructureBranch[]
}
// ---------------------------------------------------------------------------
// Type guards
// ---------------------------------------------------------------------------
// Building the structure tree
// ---------------------------------------------------------------------------
export function buildStructureTree(
modules: FlowModule[],
groups: GraphGroup[]
): FlowStructureNode[] {
const { items, consumed } = buildStructureTreeRecurse(modules, groups)
const unconsumed = groups.filter((g) => !consumed.has(g.id))
if (unconsumed.length > 0) {
throw new Error(
`Group(s) ${unconsumed.map((g) => `'${g.id}'`).join(', ')} could not be resolved: ` +
`their start/end nodes do not belong to the same branch`
)
}
return items
}
export function moduleToStructureNode(mod: FlowModule): FlowStructureNode {
const innerArrays = getContainerInnerArrays(mod)
if (innerArrays.length === 0) {
return { id: mod.id, kind: 'leaf', branches: [] }
}
const kind = (mod.value as any).type as ContainerKind
const branches: StructureBranch[] = innerArrays.map(({ get, label }) => ({
label,
children: [] // filled later by recursion
}))View on GitHub (pinned to e474e8803c)
Solutions
- Recompute groups from the current module structure before calling; discard groups referencing removed node ids.
- Ensure each group's start_id and end_id belong to the same branch when creating selections.
- Validate groups against the current graph and drop/filter invalid ones instead of passing them through.
Example fix
// before const tree = buildStructureTree(modules, groups) // after const validIds = new Set(modules.map((m) => m.id)) const safeGroups = groups.filter( (g) => validIds.has(g.start_id) && validIds.has(g.end_id) ) const tree = buildStructureTree(modules, safeGroups)
Defensive patterns
Strategy: validation
Validate before calling
const ids = new Set(modules.map((m) => m.id)) const safeGroups = groups.filter((g) => ids.has(g.start_id) && ids.has(g.end_id)) const tree = buildStructureTree(modules, safeGroups)
Type guard
function groupsReferenceKnownNodes(modules: FlowModule[], groups: GraphGroup[]): boolean {
const ids = new Set(modules.map((m) => m.id))
return groups.every((g) => ids.has(g.start_id) && ids.has(g.end_id))
} Try / catch
try {
const tree = buildStructureTree(modules, groups)
} catch (e) {
if (e.message.includes('could not be resolved')) {
groups = recomputeGroupsFromStructure(modules)
return buildStructureTree(modules, groups)
}
throw e
} Prevention
- Recompute groups whenever modules are added/removed/restructured.
- Restrict group creation to selections within a single branch.
- Purge groups referencing deleted node ids before persisting flow state.
When it happens
Trigger: Calling buildStructureTree with groups whose start_id/end_id span different branches (e.g., a group starting in the 'then' branch and ending in the 'else' branch of a branching step), or referencing ids that no longer exist after modules were edited/removed.
Common situations: Stale saved groups after deleting or restructuring branch steps; cross-branch selections made in a custom flow-graph editor; migrations or imported flows carrying group definitions from an older structure.
Related errors
- Duplicate group id: '${g.id}'
- Group '${g.id}' references virtual node: groups cannot inclu
- PlanWriteRefusedError
- Can't create script from non-inline script
- no first step found
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/282dec2dc87b5a19.
Report an issue: GitHub.