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 id as first argument, but received ${receivedId}. Example: workflow('my-workflow-id', 'My Workflow Name')

What it means

The workflow() factory requires its first argument to be a string id. A runtime TypeError guard checks typeof id === 'string' and reports the actual received type (distinguishing arrays from objects). The id is used verbatim as the workflow's stable identifier, so non-string values are rejected up front rather than causing subtle serialization issues later.

Source

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

	options: WorkflowSettings | WorkflowBuilderOptions | undefined,
): options is WorkflowBuilderOptions {
	if (!options) return false;
	// WorkflowBuilderOptions has 'settings' or 'registry' as keys
	// WorkflowSettings has keys like 'timezone', 'executionOrder', etc.
	return 'settings' in options || 'registry' in options;
}

/**
 * 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) ||

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Coerce the id to a string at the call site: workflow(String(myId), name).
  2. Fix the source so the id is already a string (e.g. store as text, or JSON.parse with a string id).
  3. Add a type annotation on the caller's id variable so TypeScript rejects non-strings at compile time.

Example fix

// before
workflow(42, 'My Workflow'); // throws

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

Strategy: type-guard

Validate before calling

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

Type guard

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

Prevention

When it happens

Trigger: Passing a number (e.g. a DB id), an object, an array, undefined, or null as the first argument to workflow(). Common when a caller reads an id from JSON/DB as a number and forwards it unchanged.

Common situations: Numeric IDs from a database; destructuring that yields undefined; loosely-typed glue code; migrated callers that previously passed any value.

Related errors


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