windmill-labs/windmill · error
Duplicate group: '${g.start_id}' → '${g.end_id}'
Error message
Duplicate group: '${g.start_id}' → '${g.end_id}' What it means
validateGroups in FlowYamlEditor.svelte rejects a flow that declares two identical group edges (same start_id and end_id pair). Duplicate branches between the same pair of modules make the flow graph ambiguous, so the editor refuses to apply the YAML.
Source
Thrown at frontend/src/lib/components/flows/header/FlowYamlEditor.svelte:57
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
throw new Error('the document must be a mapping (key: value)')
}
const value = (parsed as Record<string, unknown>).value
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
throw new Error("missing 'value' - paste a whole OpenFlow document, not just its value")
}
if (!Array.isArray((value as Record<string, unknown>).modules)) {
throw new Error("'value.modules' must be a list")
}
}
function validateGroups(groups: { start_id: string; end_id: string }[] | undefined) {
if (!groups) return
const seen = new Set<string>()
for (const g of groups) {
const key = `${g.start_id}:${g.end_id}`
if (seen.has(key)) {
throw new Error(`Duplicate group: '${g.start_id}' → '${g.end_id}'`)
}
seen.add(key)
}
}
function apply() {
try {
const parsed = YAML.parse(code)
validateShape(parsed)
validateGroups(parsed.value?.groups)
if (parsed.summary && typeof parsed.summary === 'string') {
flowStore.val.summary = parsed.summary
}
if (parsed.description && typeof parsed.description === 'string') {
flowStore.val.description = parsed.description
}
if (parsed['ws_error_handler_muted'] !== undefined) {
flowStore.val.ws_error_handler_muted = parsed['ws_error_handler_muted']View on GitHub (pinned to e474e8803c)
Solutions
- Remove one of the duplicated group entries so each (start_id, end_id) pair appears at most once
- If two branches between the same modules are intended, use branch indexes/conditional branch syntax instead of duplicate groups
- Ensure each group's start_id and end_id reference distinct, existing module ids
- Regenerate the YAML from the flow editor UI instead of hand-copying branch definitions
Example fix
// before (duplicate edge)
groups:
- start_id: a
end_id: b
- start_id: a
end_id: b
// after (single edge)
groups:
- start_id: a
end_id: b Defensive patterns
Strategy: validation
Validate before calling
const seen = new Set()
for (const g of parsed.value.groups ?? []) {
const key = `${g.start_id}:${g.end_id}`
if (seen.has(key)) { alert(`Duplicate group ${key}`); break }
seen.add(key)
} Type guard
function hasUniqueGroups(groups: { start_id: string; end_id: string }[]): boolean {
const keys = groups.map(g => `${g.start_id}:${g.end_id}`)
return new Set(keys).size === keys.length
} Try / catch
try {
editor.apply(yamlText)
} catch (e) {
if (e.message.startsWith('Duplicate group:')) {
sendUserToast(e.message + ' — remove the repeated edge', true)
}
} Prevention
- Deduplicate the groups array before applying
- Never copy-paste branch entries wholesale; verify each (start_id, end_id) pair is unique
- Generate branches programmatically from a Set of edges
- Keep module ids distinct so edges cannot collapse into duplicates
When it happens
Trigger: Calling apply() → validateGroups() when the parsed flow's groups array contains two entries with the same start_id:end_id key — e.g. copy-pasted branch definitions or two parent-children edges linking the same modules.
Common situations: Hand-editing YAML and duplicating a branch entry; merging two flow YAMLs where both defined a branch between the same modules; generating YAML programmatically and emitting the same branch twice.
Related errors
- Document must be a string
- Unsupported trigger kind: ${target.triggerKind}
- the document must be a mapping (key: value)
- missing 'value' - paste a whole OpenFlow document, not just
- 'value.modules' must be a list
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/a75020817b7b5175.
Report an issue: GitHub.