windmill-labs/windmill · error
Groups '${a.id}' and '${b.id}' overlap without nesting
Error message
Groups '${a.id}' and '${b.id}' overlap without nesting What it means
Two sibling groups at the same level must be either disjoint or strictly nested. This throw fires when two groups partially overlap (each has nodes the other lacks), which cannot be expressed as a hierarchy of nested regions in the graph.
Source
Thrown at frontend/src/lib/components/graph/flowStructure.ts:129
otherGroups.push(g)
}
}
// Validate no partial overlaps
for (let i = 0; i < levelGroups.length; i++) {
for (let j = i + 1; j < levelGroups.length; j++) {
const a = levelGroups[i]
const b = levelGroups[j]
const aStart = indexMap.get(a.start_id)!
const aEnd = indexMap.get(a.end_id)!
const bStart = indexMap.get(b.start_id)!
const bEnd = indexMap.get(b.end_id)!
if (aEnd < bStart || bEnd < aStart) continue
if (aStart <= bStart && bEnd <= aEnd) continue
if (bStart <= aStart && aEnd <= bEnd) continue
throw new Error(`Groups '${a.id}' and '${b.id}' overlap without nesting`)
}
}
// Build grouped structure for this level
function build(
startIdx: number,
endIdx: number,
availableGroups: GraphGroup[]
): FlowStructureNode[] {
const result: FlowStructureNode[] = []
let i = startIdx
while (i <= endIdx) {
const candidates = availableGroups.filter((g) => {
const gStart = indexMap.get(g.start_id)!
const gEnd = indexMap.get(g.end_id)!
return gStart === i && gEnd <= endIdx
})
candidates.sort((a, b) => {View on GitHub (pinned to e474e8803c)
Solutions
- Open the flow and adjust the two groups so one fully contains the other, or shrink them so they no longer overlap.
- Delete and redraw the conflicting group(s) in the editor to regenerate consistent boundaries.
- Compare the deployed flow JSON groups and fix the overlapping start_id/end_id pairs manually.
- If a merge introduced it, redo the merge keeping group definitions from one side only.
Example fix
// before
groups: [{ id: 'a', start_id: 's1', end_id: 's3' }, { id: 'b', start_id: 's2', end_id: 's5' }]
// after
groups: [{ id: 'a', start_id: 's1', end_id: 's5' }] // b nested or removed Defensive patterns
Strategy: validation
Validate before calling
for (let i = 0; i < groups.length; i++) for (let j = i + 1; j < groups.length; j++) {
const a = groups[i], b = groups[j]
const nested = (as <= bs && be <= ae) || (bs <= as && ae <= be)
const disjoint = ae < bs || be < as
if (!nested && !disjoint) console.warn('overlap', a.id, b.id)
} Type guard
function groupsAreHierarchical(groups, indexMap) {
return groups.every((a, i) => groups.every((b, j) => i >= j || (fn(indexMap, a, b) || fn(indexMap, b, a))))
}
const fn = (m, a, b) => { const as=m.get(a.start_id), ae=m.get(a.end_id), bs=m.get(b.start_id), be=m.get(b.end_id); return ae<bs || be<as || (as<=bs && be<=ae) } Try / catch
try { tree = buildStructureTree(items, groups) } catch (e) { if (String(e.message).includes('overlap without nesting')) showGroupConflictDialog(e); else throw e } Prevention
- Redraw groups in the editor instead of hand-editing boundaries
- Resolve overlapping groups from merges by keeping one side's definitions
- Run a hierarchical-consistency check on imported flows before rendering
When it happens
Trigger: Two GraphGroups a and b where ranges [aStart,aEnd] and [bStart,bEnd] intersect but neither contains the other — e.g. group1 covers steps 1-3 and group2 covers steps 2-5.
Common situations: Editing a flow and dragging a step into/out of a branch while stale group boundaries persist; duplicated group ids with shifted boundaries after a merge; imported flow JSON with hand-drawn group boxes that cross each other.
Related errors
- Group '${g.id}' has inverted range: start_id='${g.start_id}'
- Duplicated node detected: ${module.id}
- Cycle detected: adding edge from '${sourceId}' to '${targetI
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/1f27d068c0238c09.
Report an issue: GitHub.