n8n-io/n8n · error · TypeError

workflow() requires (id: string, name: string). workflow() r

Error message

workflow() requires (id: string, name: string). workflow() requires a string name as second argument, but received ${receivedName}. Example: workflow('my-workflow-id', 'My Workflow Name')

What it means

The workflow() factory requires its second argument to be a string name. Same guard shape as the id check: typeof name === 'string', with the received type reported. The name is stored as the workflow's human-readable name and used in serialization, so non-strings are rejected immediately.

Source

Thrown at packages/@n8n/workflow-sdk/src/workflow-builder.ts:1317

 * Create a new workflow builder
 */
function createWorkflow(
	id: string,
	name: string,
	options?: WorkflowSettings | WorkflowBuilderOptions,
): WorkflowBuilder {
	if (typeof id !== 'string') {
		const receivedId = Array.isArray(id) ? 'an array' : typeof id;
		throw new TypeError(
			// eslint-disable-next-line n8n-local-rules/no-interpolation-in-regular-string
			'workflow() requires (id: string, name: string). ' +
				`workflow() requires a string id as first argument, but received ${receivedId}. ` +
				"Example: workflow('my-workflow-id', 'My Workflow Name')",
		);
	}
	if (typeof name !== 'string') {
		const receivedName = Array.isArray(name) ? 'an array' : typeof name;
		throw new TypeError(
			// eslint-disable-next-line n8n-local-rules/no-interpolation-in-regular-string
			'workflow() requires (id: string, name: string). ' +
				`workflow() requires a string name as second argument, but received ${receivedName}. ` +
				"Example: workflow('my-workflow-id', 'My Workflow Name')",
		);
	}
	if (
		options !== undefined &&
		(Array.isArray(options) ||
			(typeof options === 'object' &&
				options !== null &&
				('nodes' in options || 'connections' in options)))
	) {
		throw new TypeError(
			'workflow() third argument is settings, not workflow structure. ' +
				'Do not pass nodes or connections here — use .add() and .to() to build the workflow. ' +
				"Example: workflow('id', 'Name').add(trigger({...})).to(node({...}))",
		);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Ensure the second argument is a string: workflow('id', String(name) || 'Untitled').
  2. Re-order arguments if they were swapped.
  3. Type the caller so a non-string name is a compile error.

Example fix

// before
workflow('id', { title: 'My Workflow' }); // throws

// after
workflow('id', 'My Workflow');
Defensive patterns

Strategy: type-guard

Validate before calling

function isStringName(v: unknown): v is string {
  return typeof v === 'string';
}
if (!isStringName(name)) name = String(name);

Type guard

function isStringName(v: unknown): v is string {
  return typeof v === 'string';
}

Prevention

When it happens

Trigger: Passing an object, number, array, null, or undefined as the name argument. Often happens when a caller swaps argument order or passes a config object where the name should go.

Common situations: Argument-order confusion (passing options before name); undefined from an optional field; numeric or object names from external data.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/7e7030ddd07da64c. Report an issue: GitHub.