{"record":{"id":"b114af640d35941a","repo":"windmill-labs/windmill","slug":"top-level-yaml-must-be-a-mapping","errorCode":null,"errorMessage":"Top-level YAML must be a mapping","messagePattern":"Top-level YAML must be a mapping","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/src/lib/components/raw_apps/RawAppYamlEditor.svelte","lineNumber":55,"sourceCode":"\t\t\tsummary,\n\t\t\tfiles: files ?? {},\n\t\t\trunnables,\n\t\t\tdata\n\t\t}\n\t\tcode = YAML.stringify(snapshot)\n\t\tinitialCode = code\n\t\teditor?.setCode(code)\n\t}\n\n\tfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n\t\treturn typeof value === 'object' && value !== null && !Array.isArray(value)\n\t}\n\n\tfunction apply() {\n\t\ttry {\n\t\t\tconst parsed = YAML.parse(code)\n\t\t\tif (!isPlainObject(parsed)) {\n\t\t\t\tthrow new Error('Top-level YAML must be a mapping')\n\t\t\t}\n\t\t\tconst update: RawAppYamlUpdate = {}\n\t\t\tif (typeof parsed.summary === 'string') {\n\t\t\t\tupdate.summary = parsed.summary\n\t\t\t}\n\t\t\tif (isPlainObject(parsed.files)) {\n\t\t\t\tupdate.files = parsed.files as Record<string, string>\n\t\t\t}\n\t\t\tif (isPlainObject(parsed.runnables)) {\n\t\t\t\tupdate.runnables = parsed.runnables as Record<string, Runnable>\n\t\t\t}\n\t\t\tif (isPlainObject(parsed.data)) {\n\t\t\t\tupdate.data = parsed.data as unknown as RawAppData\n\t\t\t}\n\t\t\tonApply(update)\n\t\t\tinitialCode = code\n\t\t\tsendUserToast('Changes applied')\n\t\t} catch (e) {","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/frontend/src/lib/components/raw_apps/RawAppYamlEditor.svelte#L37-L73","documentation":"apply() in the raw-app YAML editor parses the textarea contents with YAML.parse and requires the top-level node to be a plain object (mapping). If the YAML parses to a scalar, array, or null, it throws this error instead of applying a partial update, because the update extraction logic can only read keys (summary, files, ...) off a mapping.","triggerScenarios":"Clicking apply in the RawAppYamlEditor with YAML whose root is a list (e.g. '- a\\n- b'), a bare scalar (e.g. 'hello'), an empty document (parses to null), or multiple documents/typo leading to a non-mapping root.","commonSituations":"Pasting a files-array snippet instead of a mapping; clearing the editor and hitting apply; copy-pasting YAML with a leading '-' making it a sequence.","solutions":["Ensure the YAML root is a mapping like 'summary: ...' with 'files:' as a nested mapping, not a list or scalar","Do not apply an empty editor; restore valid YAML or reload the current app definition","Validate locally with YAML.parse and isPlainObject before clicking apply"],"exampleFix":"// before\n- app.ts\n// after\nsummary: My app\nfiles:\n  app.ts: <content>","handlingStrategy":"validation","validationCode":"import YAML from 'yaml';\nconst parsed = YAML.parse(code);\nif (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {\n  throw new Error('Top-level YAML must be a mapping');\n}","typeGuard":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try { apply(); } catch (e) {\n  if (e.message === 'Top-level YAML must be a mapping') { showYamlSyntaxHint(); }\n  else throw e;\n}","preventionTips":["Always author raw-app YAML with a mapping root (key: value), never a bare list or scalar","Lint/paste-validate YAML before clicking apply","Never apply an empty editor"],"tags":["yaml","validation","frontend"],"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"}