{"record":{"id":"77dedb831c39a0c6","repo":"windmill-labs/windmill","slug":"the-document-must-be-a-mapping-key-value","errorCode":null,"errorMessage":"the document must be a mapping (key: value)","messagePattern":"the document must be a mapping \\(key: value\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/flows/header/FlowYamlEditor.svelte","lineNumber":40,"sourceCode":"\n\tlet code = $state('')\n\tlet initialCode = $state('')\n\tlet editor = $state(undefined) as SimpleEditor | undefined\n\tlet hasChanges = $derived(code !== initialCode)\n\n\tfunction reload() {\n\t\tcode = YAML.stringify(filteredContentForExport(flowStore.val))\n\t\tinitialCode = code\n\t\teditor?.setCode(code)\n\t}\n\n\t/** `value` is assigned unconditionally below and `FlowEditor` dereferences\n\t * `flowStore.val.value.modules`, so an OpenFlow document missing it takes the\n\t * whole editor down mid-render — after the toast has already claimed success.\n\t * Reject it up front instead. */\n\tfunction validateShape(parsed: unknown) {\n\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}","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/flows/header/FlowYamlEditor.svelte#L22-L58","documentation":"validateShape in FlowYamlEditor.svelte guards against pasting YAML that is not a whole OpenFlow document. The parsed document must be a mapping (not a scalar or array); otherwise `value` assignment and downstream `flowStore.val.value.modules` access would crash the FlowEditor after a success toast.","triggerScenarios":"The user pastes YAML that parses to a scalar or a list (e.g. just the modules list, or a single key line) into the YAML editor and clicks apply; validateShape runs before storing and rejects it.","commonSituations":"Copying only the `value:` subtree instead of the full OpenFlow document; pasting a flow snippet from docs that is an array of steps; YAML with top-level sequence syntax (dashes).","solutions":["Paste the complete OpenFlow document including the top-level `value` key with a `modules` array","Wrap scalar/list YAML under a mapping, e.g. `value:\\n  modules: [...]`","Use the flow's Export function to get a correctly shaped document and edit that"],"exampleFix":"// before\n- id: a\n  value: {}\n// after\nvalue:\n  modules:\n    - id: a\n      value: {}","handlingStrategy":"validation","validationCode":"const doc = YAML.parse(text)\nif (typeof doc !== 'object' || doc === null || Array.isArray(doc)) throw new Error('Paste a whole OpenFlow mapping, not a list or scalar')\nif (!doc.value || Array.isArray(doc.value) || !Array.isArray(doc.value.modules)) throw new Error(\"Missing value.modules\")","typeGuard":"function isOpenFlowDoc(v: unknown): v is { value: { modules: unknown[] } } {\n  return typeof v === 'object' && v !== null && !Array.isArray(v) &&\n    typeof (v as any).value === 'object' && (v as any).value !== null &&\n    Array.isArray((v as any).value.modules)\n}","tryCatchPattern":"try { apply(text) } catch (e) { sendUserToast(e.message, true) }","preventionTips":["Export the flow from the UI and edit that document as a template","Never paste partial subtrees (modules-only) into the YAML editor","Run validateShape before any store write and show the message in the editor gutter"],"tags":["yaml","validation","flow-editor"],"backgroundTag":"schema-validation-failed","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"}