windmill-labs/windmill · error

Invalid worker group config

Error message

Invalid worker group config

What it means

importSingleWorkerConfig accepts only non-null plain objects as worker group configs; anything else (string, number, array element, null) hits the else branch and throws 'Invalid worker group config'. It protects ConfigService.updateConfig from being called with a shape the backend can't store.

Source

Thrown at frontend/src/routes/(root)/(logged)/workers/+page.svelte:366

	let importConfigDrawer: Drawer | undefined = $state(undefined)
	let importConfigCode = $state('')
	let tag: string = $state('')
	async function importSingleWorkerConfig(c: any) {
		if (typeof c === 'object' && c !== null) {
			if (!c.name || typeof c.name !== 'string') {
				throw new Error('Invalid worker group config name')
			}

			if (workerGroups?.hasOwnProperty(c.name)) {
				throw new Error(`Worker group config with the name ${c.name} already exists`)
			}

			await ConfigService.updateConfig({
				name: 'worker__' + c.name,
				requestBody: { ...c, name: undefined }
			})
		} else {
			throw new Error('Invalid worker group config')
		}
	}

	async function importConfigFromYaml() {
		const config = YAML.parse(importConfigCode)

		try {
			if (Array.isArray(config)) {
				for (const c of config) {
					await importSingleWorkerConfig(c)
				}
			} else {
				await importSingleWorkerConfig(config)
			}
		} catch (err) {
			if (err instanceof Error) {
				sendUserToast(err.message, true)
			} else {

View on GitHub (pinned to e474e8803c)

Solutions

  1. Ensure every worker group entry in the YAML is a mapping (key: value pairs), not a scalar or list
  2. Validate the YAML parses to the expected shape (e.g. console.log the parsed object) before importing
  3. Fix indentation so nested fields belong to the group object
  4. Start from a known-good exported config as a template

Example fix

// before
worker_groups:
  - group-a
  - group-b
// after
worker_groups:
  - name: group-a
    concurrency: 5
  - name: group-b
    concurrency: 5
Defensive patterns

Strategy: type-guard

Validate before calling

const parsed = YAML.parse(importConfigCode)
const entries = Array.isArray(parsed) ? parsed : parsed?.worker_groups ?? []
if (!entries.every(c => typeof c === 'object' && c !== null && !Array.isArray(c))) {
  sendUserToast('Every worker group must be a YAML mapping of key/value pairs', true)
  return
}

Type guard

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

Try / catch

try {
  await importConfigFromYaml()
} catch (e) {
  if (e.message === 'Invalid worker group config') {
    sendUserToast('YAML entries must be mappings like { name: ..., concurrency: ... }, not scalars', true)
  } else throw e
}

Prevention

When it happens

Trigger: YAML where a worker_groups list contains scalar entries (e.g. just names as strings), the parsed top-level is a list instead of objects, or YAML.parse produced null/undefined for a malformed block.

Common situations: Writing 'worker_groups: [groupA, groupB]' instead of a list of maps; broken YAML indentation collapsing a group to a scalar; pasting JSON with quoted-but-wrong structure; empty file parsing to null.

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/bbb4f519c3c1a589. Report an issue: GitHub.