windmill-labs/windmill · error

Top-level YAML must be a mapping

Error message

Top-level YAML must be a mapping

What it means

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.

Source

Thrown at frontend/src/lib/components/raw_apps/RawAppYamlEditor.svelte:55

			summary,
			files: files ?? {},
			runnables,
			data
		}
		code = YAML.stringify(snapshot)
		initialCode = code
		editor?.setCode(code)
	}

	function isPlainObject(value: unknown): value is Record<string, unknown> {
		return typeof value === 'object' && value !== null && !Array.isArray(value)
	}

	function apply() {
		try {
			const parsed = YAML.parse(code)
			if (!isPlainObject(parsed)) {
				throw new Error('Top-level YAML must be a mapping')
			}
			const update: RawAppYamlUpdate = {}
			if (typeof parsed.summary === 'string') {
				update.summary = parsed.summary
			}
			if (isPlainObject(parsed.files)) {
				update.files = parsed.files as Record<string, string>
			}
			if (isPlainObject(parsed.runnables)) {
				update.runnables = parsed.runnables as Record<string, Runnable>
			}
			if (isPlainObject(parsed.data)) {
				update.data = parsed.data as unknown as RawAppData
			}
			onApply(update)
			initialCode = code
			sendUserToast('Changes applied')
		} catch (e) {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Ensure the YAML root is a mapping like 'summary: ...' with 'files:' as a nested mapping, not a list or scalar
  2. Do not apply an empty editor; restore valid YAML or reload the current app definition
  3. Validate locally with YAML.parse and isPlainObject before clicking apply

Example fix

// before
- app.ts
// after
summary: My app
files:
  app.ts: <content>
Defensive patterns

Strategy: validation

Validate before calling

import YAML from 'yaml';
const parsed = YAML.parse(code);
if (parsed === null || typeof parsed !== 'object' || Array.isArray(parsed)) {
  throw new Error('Top-level YAML must be a mapping');
}

Type guard

function isPlainObject(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

try { apply(); } catch (e) {
  if (e.message === 'Top-level YAML must be a mapping') { showYamlSyntaxHint(); }
  else throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03). Data as JSON: /api/errors/b114af640d35941a. Report an issue: GitHub.