windmill-labs/windmill · error · Error

Invalid group at index ${index}: start_id "${g.start_id}" do

Error message

Invalid group at index ${index}: start_id "${g.start_id}" does not match any flow module

What it means

validateFlowGroups validates the `groups` array an AI agent passes to patch_flow_json/set_flow_json. Each group's start_id and end_id must reference an existing flow module; when a moduleIds set is supplied and start_id is not found in it, this error is thrown. It exists to prevent groups that visually dangle on the canvas because they point at modules that don't exist.

Source

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

		}
		if (typeof g.end_id !== 'string' || !g.end_id) {
			throw new Error(`Invalid group at index ${index}: end_id must be a non-empty string`)
		}
		if (moduleIds) {
			if (!moduleIds.has(g.start_id)) {
				throw new Error(
					`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

View on GitHub (pinned to e474e8803c)

Solutions

  1. Copy module ids verbatim from the flow value the tools returned (each module's `id` field), never invent them
  2. Re-fetch the current flow JSON to see which module ids actually exist before setting groups
  3. If the module was intended to be new, add the module itself in the same update and use its generated id
  4. Drop or fix the offending group entry at the reported index

Example fix

// before
groups: [{ start_id: 'step_1', end_id: 'step_2' }]
// after — use real ids from flow.value.modules
groups: [{ start_id: flow.value.modules[0].id, end_id: flow.value.modules[1].id }]
Defensive patterns

Strategy: validation

Validate before calling

const moduleIds = new Set<string>(); forEachFlowModule(flow.value, (m) => { moduleIds.add(m.id); });
for (const [i, g] of (groups ?? []).entries()) {
  if (!moduleIds.has(g.start_id)) throw new Error(`groups[${i}].start_id "${g.start_id}" is not a flow module id`);
}

Type guard

function isValidGroupId(id: unknown, moduleIds: Set<string>): id is string {
  return typeof id === 'string' && moduleIds.has(id);
}

Try / catch

try {
  const validated = validateFlowGroups(rawGroups, moduleIds);
} catch (e) {
  if (e instanceof Error && e.message.includes('does not match any flow module')) {
    // surface index + offending id back to the agent so it can re-read the flow
  } else throw e;
}

Prevention

When it happens

Trigger: Calling updateFlowJson/patch_flow_json with groups: [{start_id: 'mod_x', end_id: 'mod_y'}] where 'mod_x' is not a module id in the current flow (typo, hallucinated id by the LLM, or a module deleted earlier in the same edit).

Common situations: An LLM agent invents plausible-looking module ids instead of copying them from the flow it was given; the agent references a module from a previous flow revision that was renamed or removed; the caller forgets to include newly-added module ids in the moduleIds set.

Related errors


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