windmill-labs/windmill · error · Error
Invalid note at index ${index}: id must be a non-empty strin
Error message
Invalid note at index ${index}: id must be a non-empty string What it means
Thrown by validateFlowNotes when the flow note at `index` lacks a non-empty string `id`. Notes are keyed into the flow draft by id and auto-placement needs a stable identity, so LLM-supplied note arrays without ids are rejected by this guard before the draft is written.
Source
Thrown at frontend/src/lib/components/copilot/chat/flow/helperUtils.ts:173
if (!Array.isArray(rawNotes)) {
throw new Error('Flow notes must be an array')
}
const seenIds = new Set<string>()
// Column and running y-cursor for auto-placed free notes so consecutive ones
// stack below each other by their actual heights instead of overlapping. A
// preserved note (explicit geometry) sitting in this column also advances the
// cursor, so a later auto-placed note doesn't land on top of it.
const AUTO_STACK_X = -(MIN_NOTE_WIDTH + 100)
const AUTO_STACK_GAP = 24
let autoStackY = 0
return rawNotes.map((note, index) => {
if (!note || typeof note !== 'object' || Array.isArray(note)) {
throw new Error(`Invalid note at index ${index}: must be an object`)
}
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(', ')}`
)
}View on GitHub (pinned to e474e8803c)
Solutions
- Add a unique non-empty string id to every note, e.g. id: 'note-1'
- Convert numeric ids to strings before passing
- Generate ids yourself (e.g. crypto.randomUUID()) when creating notes programmatically
Example fix
// before
notes: [{ text: 'Review auth flow' }]
// after
notes: [{ id: 'note-1', text: 'Review auth flow' }] Defensive patterns
Strategy: validation
Validate before calling
notes.forEach((n, i) => {
if (typeof n.id !== 'string' || !n.id) throw new Error(`notes[${i}].id must be a non-empty string`);
}); Type guard
function hasNoteId(n: unknown): n is { id: string } & Record<string, unknown> {
return typeof (n as any)?.id === 'string' && (n as any).id.length > 0;
} Try / catch
try {
validateFlowNotes(rawNotes, moduleIds);
} catch (e) {
if (e instanceof Error && e.message.includes('id must be a non-empty string')) {
// regenerate ids and retry
} else throw e;
} Prevention
- Assign an explicit unique string id to every note at creation time
- Use randomUUID() when generating ids programmatically
- Never rely on the validator to auto-fill note ids — it does not
When it happens
Trigger: notes: [{ text: 'hi' }], notes: [{ id: '', text: 'hi' }], or notes: [{ id: 42, text: 'hi' }] passed to patch_flow_json/set_flow_json.
Common situations: An LLM agent omits ids for brevity; a caller assumes ids are auto-generated (they are not, unlike UI-created notes); numeric database keys were passed instead of strings.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Invalid note at index ${index}: duplicate note id "${n.id}"
- Invalid note at index ${index}: text must be a string
- Flow notes must be an array
- Invalid note at index ${index}: must be an object
- Invalid note at index ${index}: type must be "free" or "grou
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/49b49c2e9fb0c40a.
Report an issue: GitHub.