{"record":{"id":"a75020817b7b5175","repo":"windmill-labs/windmill","slug":"duplicate-group-g-start-id-g-end-id","errorCode":null,"errorMessage":"Duplicate group: '${g.start_id}' → '${g.end_id}'","messagePattern":"Duplicate group: '(.+?)' → '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/flows/header/FlowYamlEditor.svelte","lineNumber":57,"sourceCode":"\t\tif (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n\t\t\tthrow new Error('the document must be a mapping (key: value)')\n\t\t}\n\t\tconst value = (parsed as Record<string, unknown>).value\n\t\tif (typeof value !== 'object' || value === null || Array.isArray(value)) {\n\t\t\tthrow new Error(\"missing 'value' - paste a whole OpenFlow document, not just its value\")\n\t\t}\n\t\tif (!Array.isArray((value as Record<string, unknown>).modules)) {\n\t\t\tthrow new Error(\"'value.modules' must be a list\")\n\t\t}\n\t}\n\n\tfunction validateGroups(groups: { start_id: string; end_id: string }[] | undefined) {\n\t\tif (!groups) return\n\t\tconst seen = new Set<string>()\n\t\tfor (const g of groups) {\n\t\t\tconst key = `${g.start_id}:${g.end_id}`\n\t\t\tif (seen.has(key)) {\n\t\t\t\tthrow new Error(`Duplicate group: '${g.start_id}' → '${g.end_id}'`)\n\t\t\t}\n\t\t\tseen.add(key)\n\t\t}\n\t}\n\n\tfunction apply() {\n\t\ttry {\n\t\t\tconst parsed = YAML.parse(code)\n\t\t\tvalidateShape(parsed)\n\t\t\tvalidateGroups(parsed.value?.groups)\n\t\t\tif (parsed.summary && typeof parsed.summary === 'string') {\n\t\t\t\tflowStore.val.summary = parsed.summary\n\t\t\t}\n\t\t\tif (parsed.description && typeof parsed.description === 'string') {\n\t\t\t\tflowStore.val.description = parsed.description\n\t\t\t}\n\t\t\tif (parsed['ws_error_handler_muted'] !== undefined) {\n\t\t\t\tflowStore.val.ws_error_handler_muted = parsed['ws_error_handler_muted']","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/flows/header/FlowYamlEditor.svelte#L39-L75","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before (duplicate edge)\ngroups:\n  - start_id: a\n    end_id: b\n  - start_id: a\n    end_id: b\n// after (single edge)\ngroups:\n  - start_id: a\n    end_id: b","handlingStrategy":"validation","validationCode":"const seen = new Set()\nfor (const g of parsed.value.groups ?? []) {\n  const key = `${g.start_id}:${g.end_id}`\n  if (seen.has(key)) { alert(`Duplicate group ${key}`); break }\n  seen.add(key)\n}","typeGuard":"function hasUniqueGroups(groups: { start_id: string; end_id: string }[]): boolean {\n  const keys = groups.map(g => `${g.start_id}:${g.end_id}`)\n  return new Set(keys).size === keys.length\n}","tryCatchPattern":"try {\n  editor.apply(yamlText)\n} catch (e) {\n  if (e.message.startsWith('Duplicate group:')) {\n    sendUserToast(e.message + ' — remove the repeated edge', true)\n  }\n}","preventionTips":["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"],"tags":["yaml","validation","flow-graph"],"backgroundTag":"duplicate-definition","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"}