windmill-labs/windmill · error · Error
Invalid note at index ${index}: color must be one of ${[...A
Error message
Invalid note at index ${index}: color must be one of ${[...ALLOWED_NOTE_COLORS].join(', ')} What it means
Note colors are restricted to the NoteColor palette (yellow, blue, green, purple, pink, orange, red, cyan, lime, gray) because the renderer styles notes by these exact names. A non-string color or a string outside the palette throws this error in validateFlowNotes.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:188
}
const n = note as Record<string, unknown>
if (typeof n.id !== 'string' || !n.id) {
throw new Error(`Invalid note at index ${index}: id must be a non-empty string`)
}
if (seenIds.has(n.id)) {
throw new Error(`Invalid note at index ${index}: duplicate note id "${n.id}"`)
}
seenIds.add(n.id)
if (typeof n.text !== 'string') {
throw new Error(`Invalid note at index ${index}: text must be a string`)
}
const type = n.type ?? 'free'
if (type !== 'free' && type !== 'group') {
throw new Error(`Invalid note at index ${index}: type must be "free" or "group"`)
}
if (n.color !== undefined && n.color !== null) {
if (typeof n.color !== 'string' || !ALLOWED_NOTE_COLORS.has(n.color)) {
throw new Error(
`Invalid note at index ${index}: color must be one of ${[...ALLOWED_NOTE_COLORS].join(', ')}`
)
}
}
if (n.position !== undefined && n.position !== null) {
const p = n.position as Record<string, unknown>
if (
typeof p !== 'object' ||
Array.isArray(n.position) ||
typeof p.x !== 'number' ||
typeof p.y !== 'number'
) {
throw new Error(
`Invalid note at index ${index}: position must be an object with numeric x and y`
)
}
}
if (n.size !== undefined && n.size !== null) {View on GitHub (pinned to e474e8803c)
Solutions
- Use one of the palette names exactly: yellow, blue, green, purple, pink, orange, red, cyan, lime, gray
- Omit color (undefined/null) to let the validator fill in the default note color
- Map hex/CSS colors to the nearest palette name before sending
Example fix
// before
notes: [{ id: 'n1', text: 'x', color: '#FF0000' }]
// after
notes: [{ id: 'n1', text: 'x', color: 'red' }] Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['yellow','blue','green','purple','pink','orange','red','cyan','lime','gray'];
notes.forEach((n, i) => {
if (n.color != null && !ALLOWED.includes(n.color)) throw new Error(`notes[${i}].color "${n.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 {
validateFlowNotes(rawNotes, 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
- Restrict color choices to the ten palette names in any tooling that builds notes
- Omit color to get DEFAULT_NOTE_COLOR filled in automatically
- Translate hex/CSS colors to the nearest palette name at payload-construction time
When it happens
Trigger: notes: [{ id: 'n1', text: 'x', color: '#fff3cd' }] or color: 'amber' or color: 1 passed to patch_flow_json/set_flow_json.
Common situations: An LLM agent outputs hex codes or CSS color names outside the palette; a numeric enum index was passed; colors were copied from another design system's 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
- Invalid group at index ${index}: color must be one of ${[...
- Invalid note at index ${index}: type must be "free" or "grou
- Flow notes must be an array
- Invalid note at index ${index}: must be an object
- Invalid note at index ${index}: id must be a non-empty strin
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/00d73a230bffd16d.
Report an issue: GitHub.