windmill-labs/windmill · error · Error

Invalid note at index ${index}: size must be an object with

Error message

Invalid note at index ${index}: size must be an object with numeric width and height

What it means

validateFlowNotes also checks the optional `size` of each flow note: when supplied it must be a plain object with numeric `width` and `height`. The library throws this error to reject sizes given in the wrong shape or with non-numeric values before notes are rendered on the flow.

Source

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

				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) {
			const s = n.size as Record<string, unknown>
			if (
				typeof s !== 'object' ||
				Array.isArray(n.size) ||
				typeof s.width !== 'number' ||
				typeof s.height !== 'number'
			) {
				throw new Error(
					`Invalid note at index ${index}: size must be an object with numeric width and height`
				)
			}
		}
		if (type === 'group' && n.contained_node_ids !== undefined) {
			if (
				!Array.isArray(n.contained_node_ids) ||
				n.contained_node_ids.some((id) => typeof id !== 'string')
			) {
				throw new Error(
					`Invalid note at index ${index}: contained_node_ids must be an array of strings`
				)
			}
			if (moduleIds) {
				for (const id of n.contained_node_ids as string[]) {
					if (!moduleIds.has(id)) {
						throw new Error(
							`Invalid note at index ${index}: contained_node_ids "${id}" does not match any flow module`

View on GitHub (pinned to e474e8803c)

Solutions

  1. Coerce to numbers in an object: size: { width: Number(w), height: Number(h) }.
  2. Strip units from CSS-like strings before passing (parse "200px" to 200).
  3. Omit `size` to let the validator compute a size from the note text.
  4. Inspect the note at the reported index for the malformed size field.

Example fix

// before
notes: [{ id: 'n1', text: 'todo', size: { width: '200', height: '100' } }]
// after
notes: [{ id: 'n1', text: 'todo', size: { width: 200, height: 100 } }]
Defensive patterns

Strategy: validation

Validate before calling

function hasValidSize(n) {
  return n.size == null ||
    (typeof n.size === 'object' && !Array.isArray(n.size) &&
     typeof n.size.width === 'number' && typeof n.size.height === 'number')
}
notes.forEach((n, i) => { if (!hasValidSize(n)) throw new Error(`note ${i}: bad size`) })

Type guard

function isSize(s): s is { width: number; height: number } {
  return typeof s === 'object' && s !== null && !Array.isArray(s) &&
    typeof (s as any).width === 'number' && typeof (s as any).height === 'number'
}

Try / catch

try {
  validateFlowNotes(notes)
} catch (e) {
  if (e.message.includes('size')) console.warn('dropping note size, will size from text')
}

Prevention

When it happens

Trigger: Passing notes[i].size as "200x100", an array [200,100], or {width: "200", height: "100"} (string values), or omitting one of width/height, when invoking the note/flowTools tool.

Common situations: LLM-generated size fields arrive as strings; a caller copies CSS-style dimensions ("200px"); size is passed as a two-element array by habit from canvas APIs.

Related errors


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