windmill-labs/windmill · error · Error

Invalid group at index ${index}: color must be one of ${[...

Error message

Invalid group at index ${index}: color must be one of ${[...ALLOWED_NOTE_COLORS].join(', ')}

What it means

validateFlowGroups restricts group colors to the NoteColor palette (yellow, blue, green, purple, pink, orange, red, cyan, lime, gray) because the renderer keys its styles by these exact names; arbitrary strings like hex codes would render unstyled or break the color picker. A non-string color, or a string outside the palette, throws this error.

Source

Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:128

					`Invalid group at index ${index}: start_id "${g.start_id}" does not match any flow module`
				)
			}
			if (!moduleIds.has(g.end_id)) {
				throw new Error(
					`Invalid group at index ${index}: end_id "${g.end_id}" does not match any flow module`
				)
			}
		}
		if (g.color !== undefined && g.color !== null) {
			if (typeof g.color !== 'string' || !ALLOWED_NOTE_COLORS.has(g.color)) {
				throw new Error(
					`Invalid group at index ${index}: color must be one of ${[...ALLOWED_NOTE_COLORS].join(', ')}`
				)
			}
		}
		return g as unknown as FlowGroup
	})
}

/**
 * Validate the optional array of sticky notes the agent attached to the flow.
 * Notes are editor-only annotations and do not affect execution.
 *
 * `free` notes are the supported kind (standalone canvas annotations). The
 * `group` note type is deprecated for creation — the chat prompt steers the
 * agent toward `groups` instead — but it is still ACCEPTED here so flows that
 * already contain group notes round-trip cleanly through `patch_flow_json` /
 * `set_flow_json` rather than being rejected. When `moduleIds` is provided,
 * every `contained_node_ids` entry of a `group` note must reference an existing
 * module.
 *
 * A provided palette `color` is always preserved as-is; the default is only
 * filled in when a note omits `color` entirely (FlowNote.color is required).
 *
 * Free notes are also given a concrete `position` and `size` when missing. A
 * free note without geometry is not draggable/resizable in the editor (you'd

View on GitHub (pinned to e474e8803c)

Solutions

  1. Use one of the palette names exactly: yellow, blue, green, purple, pink, orange, red, cyan, lime, gray
  2. Omit the color field entirely (undefined/null is accepted) to get the default color
  3. Map any hex/CSS value to the nearest palette name before sending

Example fix

// before
groups: [{ start_id: 'a', end_id: 'b', color: '#3498db' }]
// after
groups: [{ start_id: 'a', end_id: 'b', color: 'blue' }]
Defensive patterns

Strategy: validation

Validate before calling

const ALLOWED = ['yellow','blue','green','purple','pink','orange','red','cyan','lime','gray'];
for (const [i, g] of (groups ?? []).entries()) {
  if (g.color != null && !ALLOWED.includes(g.color)) throw new Error(`groups[${i}].color "${g.color}" not in palette`);
}

Type guard

function isNoteColor(c: unknown): c is NoteColor {
  return typeof c === 'string' && (Object.values(NoteColor) as string[]).includes(c);
}

Try / catch

try {
  validateFlowGroups(rawGroups, moduleIds);
} catch (e) {
  if (e instanceof Error && e.message.includes('color must be one of')) {
    // retry with color omitted to accept the default
  } else throw e;
}

Prevention

When it happens

Trigger: groups: [{ start_id, end_id, color: '#ff0000' }] or color: 'azure' or color: 3 passed to patch_flow_json/set_flow_json.

Common situations: An LLM agent outputs hex/CSS color values instead of palette names; a caller passes a numeric enum index instead of the string name; copy-pasted group config from another tool uses different color vocabulary.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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