n8n-io/n8n · error · TypeError
${fnName}() requires ${hint}, but received ${received}.
Error message
${fnName}() requires ${hint}, but received ${received}. What it means
A runtime guard inside the workflow-builder SDK. assertPlainObject() rejects any value that is not a plain object: null, arrays, strings, numbers, booleans, and undefined all fail. It is called by builder helpers (e.g. node config, parameters, settings) to enforce that the caller passed a real object before the builder spreads or iterates its keys. The thrown TypeError carries the offending function name, a human hint about what was expected, and the actual received type so the caller can pinpoint the bad argument.
Source
Thrown at packages/@n8n/workflow-sdk/src/workflow-builder/validation-helpers.ts:16
/**
* Validation helper functions for workflow builder
* Pure functions extracted from WorkflowBuilderImpl
*/
import { isPlaceholderValue } from './string-utils';
import { isTriggerNodeType } from '../utils/trigger-detection';
/**
* Assert that input is a plain (non-null, non-array) object.
* Throws a descriptive TypeError when called with a string, number, null, or array.
*/
export function assertPlainObject(input: unknown, fnName: string, hint: string): void {
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
const received = input === null ? 'null' : Array.isArray(input) ? 'an array' : typeof input;
throw new TypeError(`${fnName}() requires ${hint}, but received ${received}.`);
}
}
/**
* Check if a value contains an n8n expression
*/
export function containsExpression(value: unknown): boolean {
if (typeof value !== 'string') {
return false;
}
return value.includes('={{') || value.startsWith('=');
}
/**
* Check if a value contains a malformed expression ({{ $ without = prefix)
*/
export function containsMalformedExpression(value: unknown): boolean {
if (typeof value !== 'string') {View on GitHub (pinned to 5ac6606e81)
Solutions
- Inspect the received type in the error message, then fix the call site to pass a plain object (e.g. JSON.parse the string, replace null with {}, unwrap the array element).
- If the value legitimately may be absent, pass an explicit empty object {} or guard the call with a conditional.
- Add a type annotation at the call site so TypeScript catches the mismatch at compile time instead of at runtime.
Example fix
// before
workflow.add(trigger({ parameters: '{"a":1}' }));
// after
workflow.add(trigger({ parameters: JSON.parse('{"a":1}') })); Defensive patterns
Strategy: type-guard
Validate before calling
function isPlainObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
}
if (!isPlainObject(config)) {
throw new Error('config must be a plain object');
} Type guard
function isPlainObject(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
} Try / catch
try {
assertPlainObject(params, 'trigger', 'a parameters object');
} catch (e) {
if (e instanceof TypeError) {
console.error('Bad parameters for trigger():', e.message);
// fallback or rethrow
}
throw e;
} Prevention
- Parse JSON config with JSON.parse before passing to builder factories.
- Type all builder arguments explicitly so non-object values are compile errors.
- Default optional object arguments to {} rather than passing undefined/null.
When it happens
Trigger: Calling a builder factory or helper with a non-object argument where an object is required: passing a JSON string instead of a parsed object to a parameters/config field, passing null for an optional-but-object-typed argument, passing an array where a parameters object is expected, or passing a number/boolean from a loosely-typed caller. The check fires synchronously on the first invalid argument before any node is constructed.
Common situations: A user reads config from an env var or file as a string and forgets JSON.parse(); a caller spreads undefined into a config object and the merged value becomes undefined; a typed-as-any integration passes a primitive where the SDK expects a parameters bag; migration code that previously accepted loose input now hits the stricter guard.
Related errors
- workflow() requires (id: string, name: string). workflow() r
- workflow() requires (id: string, name: string). workflow() r
- INVALID_CONNECTION
- VALIDATION_ERROR
- SELF_CONNECTION
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/c6df6343bf890332.
Report an issue: GitHub.