{"record":{"id":"c6df6343bf890332","repo":"n8n-io/n8n","slug":"fnname-requires-hint-but-received-recei","errorCode":null,"errorMessage":"${fnName}() requires ${hint}, but received ${received}.","messagePattern":"(.+?)\\(\\) requires (.+?), but received (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/workflow-builder/validation-helpers.ts","lineNumber":16,"sourceCode":"/**\n * Validation helper functions for workflow builder\n * Pure functions extracted from WorkflowBuilderImpl\n */\n\nimport { isPlaceholderValue } from './string-utils';\nimport { isTriggerNodeType } from '../utils/trigger-detection';\n\n/**\n * Assert that input is a plain (non-null, non-array) object.\n * Throws a descriptive TypeError when called with a string, number, null, or array.\n */\nexport function assertPlainObject(input: unknown, fnName: string, hint: string): void {\n\tif (typeof input !== 'object' || input === null || Array.isArray(input)) {\n\t\tconst received = input === null ? 'null' : Array.isArray(input) ? 'an array' : typeof input;\n\t\tthrow new TypeError(`${fnName}() requires ${hint}, but received ${received}.`);\n\t}\n}\n\n/**\n * Check if a value contains an n8n expression\n */\nexport function containsExpression(value: unknown): boolean {\n\tif (typeof value !== 'string') {\n\t\treturn false;\n\t}\n\treturn value.includes('={{') || value.startsWith('=');\n}\n\n/**\n * Check if a value contains a malformed expression ({{ $ without = prefix)\n */\nexport function containsMalformedExpression(value: unknown): boolean {\n\tif (typeof value !== 'string') {","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/workflow-builder/validation-helpers.ts#L1-L34","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nworkflow.add(trigger({ parameters: '{\"a\":1}' }));\n\n// after\nworkflow.add(trigger({ parameters: JSON.parse('{\"a\":1}') }));","handlingStrategy":"type-guard","validationCode":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}\n\nif (!isPlainObject(config)) {\n  throw new Error('config must be a plain object');\n}","typeGuard":"function isPlainObject(v: unknown): v is Record<string, unknown> {\n  return typeof v === 'object' && v !== null && !Array.isArray(v);\n}","tryCatchPattern":"try {\n  assertPlainObject(params, 'trigger', 'a parameters object');\n} catch (e) {\n  if (e instanceof TypeError) {\n    console.error('Bad parameters for trigger():', e.message);\n    // fallback or rethrow\n  }\n  throw e;\n}","preventionTips":["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."],"tags":["workflow-builder","validation","typescript","typeerror"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}