windmill-labs/windmill · error

Duplicate module IDs found in flow

Error message

Duplicate module IDs found in flow

What it means

The set-flow tool collects every module ID from the modules array plus the preprocessor and failure modules and rejects the payload if any ID appears twice. Duplicate IDs would make the flow graph ambiguous (edges and step references could not be resolved uniquely), so the tool fails fast before writing anything to the editor.

Source

Thrown at frontend/src/lib/components/copilot/chat/flow/core.ts:766

				const effectiveModules =
					parsedModules ?? helpers.getFlowAndSelectedId().flow.value.modules ?? []
				const moduleIdsForGroups = new Set(collectAllFlowModuleIdsFromModules(effectiveModules))
				if (parsedGroups !== undefined) {
					parsedGroups = validateFlowGroups(parsedGroups, moduleIdsForGroups)
				}
				if (parsedNotes !== undefined) {
					parsedNotes = validateFlowNotes(parsedNotes, moduleIdsForGroups)
				}
			}

			const ids = [
				...(parsedModules ? collectAllFlowModuleIdsFromModules(parsedModules) : []),
				...[parsedPreprocessorModule, parsedFailureModule]
					.filter((module): module is FlowModule => module !== undefined && module !== null)
					.map((module) => module.id)
			]
			if (ids.length !== new Set(ids).size) {
				throw new Error('Duplicate module IDs found in flow')
			}

			toolCallbacks.setToolStatus(toolId, {
				content: `Setting flow...`
			})
			const updateResult = await helpers.setFlowJson({
				...(parsedModules !== undefined ? { modules: parsedModules } : {}),
				...(parsedSchema !== undefined ? { schema: parsedSchema } : {}),
				...(parsedPreprocessorModule !== undefined
					? { preprocessorModule: parsedPreprocessorModule }
					: {}),
				...(parsedFailureModule !== undefined ? { failureModule: parsedFailureModule } : {}),
				...(parsedGroups !== undefined ? { groups: parsedGroups } : {}),
				...(parsedNotes !== undefined ? { notes: parsedNotes } : {})
			})
			const warning = formatEmptyInlineScriptWarning(updateResult)

			// Update exprsToSet if the selected module has input_transforms

View on GitHub (pinned to e474e8803c)

Solutions

  1. Assign a fresh unique ID to the duplicated module (or remove the redundant copy) and resubmit.
  2. Check that preprocessor_module/failure_module IDs don't also appear in the modules array.
  3. List all IDs first (collect them from the payload) and de-duplicate before calling set_flow.
  4. When copying a branch/step, always rename the copied module's ID to a new unique value.

Example fix

// before: duplicate id
setFlow({ modules: [{ id: 'step1', ... }, { id: 'step1', ... }] })
// after
setFlow({ modules: [{ id: 'step1', ... }, { id: 'step2', ... }] })
Defensive patterns

Strategy: validation

Validate before calling

const ids = modules.map((m) => m.id)
if (new Set(ids).size !== ids.length) throw new Error('De-duplicate module IDs before calling set_flow')

Type guard

function hasUniqueIds(modules: { id: string }[]): boolean {
  return new Set(modules.map((m) => m.id)).size === modules.length
}

Try / catch

try {
  await setFlow(payload)
} catch (e) {
  if (e.message === 'Duplicate module IDs found in flow') {
    const fixed = renameDuplicateIds(payload)
    await setFlow(fixed)
  } else throw e
}

Prevention

When it happens

Trigger: set_flow where the same module id appears in two entries of modules, or the same id is used both inside modules and as preprocessor_module/failure_module.

Common situations: The model duplicates a step when regenerating the flow (copy/paste of a branch without renaming IDs); a template payload was appended to an existing modules list without ID renaming; a special module was accidentally duplicated in both a dedicated field and modules.

Related errors


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