{"record":{"id":"03658567e26b3510","repo":"n8n-io/n8n","slug":"name-is-a-reserved-sdk-function-name-and-cann","errorCode":null,"errorMessage":"'${name}' is a reserved SDK function name and cannot be used as a variable name. Use a different name like 'my${Name}'.","messagePattern":"'(.+?)' is a reserved SDK function name and cannot be used as a variable name\\. Use a different name like 'my(.+?)'\\.","errorType":"exception","errorClass":"SecurityError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts","lineNumber":125,"sourceCode":"\t\t\t\t\t'Destructuring in variable declaration',\n\t\t\t\t\tdeclarator.loc ?? undefined,\n\t\t\t\t\tthis.sourceCode,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst name = declarator.id.name;\n\n\t\t\t// Check for SDK function name collisions\n\t\t\tif (isAllowedSDKFunction(name)) {\n\t\t\t\tif (isAutoRenameableSDKFunction(name)) {\n\t\t\t\t\t// Auto-rename subnode variables that collide with SDK function names\n\t\t\t\t\tconst safeName = this.generateSafeName(name);\n\t\t\t\t\tconst value = declarator.init ? this.evaluate(declarator.init) : undefined;\n\t\t\t\t\tthis.renamedVariables.set(name, safeName);\n\t\t\t\t\tthis.variables.set(safeName, value);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new SecurityError(\n\t\t\t\t\tname,\n\t\t\t\t\tdeclarator.loc ?? undefined,\n\t\t\t\t\tthis.sourceCode,\n\t\t\t\t\t`'${name}' is a reserved SDK function name and cannot be used as a variable name. ` +\n\t\t\t\t\t\t`Use a different name like 'my${name.charAt(0).toUpperCase() + name.slice(1)}'.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst value = declarator.init ? this.evaluate(declarator.init) : undefined;\n\t\t\tthis.variables.set(name, value);\n\t\t}\n\t}\n\n\t/**\n\t * Evaluate an expression and return its value.\n\t */\n\tprivate evaluate(node: ESTree.Expression | ESTree.SpreadElement | null): unknown {\n\t\tif (node === null) return undefined;","sourceCodeStart":107,"sourceCodeEnd":143,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts#L107-L143","documentation":"The SDK injects top-level builder functions (`workflow`, `node`, `trigger`, `ifElse`, etc.) into the interpreter scope. Declaring a variable whose name matches a non-auto-renameable SDK function would shadow that builder and silently break workflow construction, so the interpreter throws a `SecurityError`. Auto-renameable subnode functions (`tool`, `memory`, `languageModel`, etc.) are silently renamed to `myTool`, `myMemory`, etc. instead of throwing.","triggerScenarios":"Writing `const node = 'Http'` or `const workflow = myConfig` in SDK code. At interpreter.ts:116, `isAllowedSDKFunction(name)` returns true; at line 117, `isAutoRenameableSDKFunction(name)` returns false for core builders and control-flow functions, so execution reaches the `throw new SecurityError` at line 125. The non-renameable names are: `workflow`, `node`, `trigger`, `sticky`, `placeholder`, `newCredential`, `ifElse`, `switchCase`, `merge`, `splitInBatches`, `nextBatch`, `fromAi`, `nodeJson`.","commonSituations":"Using `node` as a generic iteration or config variable; naming a config object `workflow`; refactoring code that used these words before they became SDK reserved names.","solutions":["Rename the variable — the error message suggests `my${CapitalizedName}` (e.g., `myNode`, `myWorkflow`)","Use a domain-specific name: `httpNode` instead of `node`, `wfConfig` instead of `workflow`","If the name is a subnode builder (`tool`, `memory`, etc.), the auto-rename handles it — but avoid relying on the rename for readability"],"exampleFix":"// before\nconst node = trigger({ type: 'manual' });\n\n// after\nconst manualTrigger = trigger({ type: 'manual' });","handlingStrategy":"validation","validationCode":"import {\n  ALLOWED_SDK_FUNCTIONS,\n  AUTO_RENAMEABLE_SDK_FUNCTIONS,\n} from '@n8n/workflow-sdk/ast-interpreter/validators';\n\nconst RESERVED = new Set(\n  [...ALLOWED_SDK_FUNCTIONS].filter((n) => !AUTO_RENAMEABLE_SDK_FUNCTIONS.has(n)),\n);\n\nfunction checkVarNames(code: string): string[] {\n  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });\n  const violations: string[] = [];\n  walk(ast, (node) => {\n    if (\n      node.type === 'VariableDeclarator' &&\n      node.id.type === 'Identifier' &&\n      RESERVED.has(node.id.name)\n    ) {\n      violations.push(node.id.name);\n    }\n  });\n  return violations;\n}","typeGuard":null,"tryCatchPattern":"import { SecurityError } from '@n8n/workflow-sdk/ast-interpreter/errors';\n\ntry {\n  interpretSDKCode(sdkCode, sdkFunctions);\n} catch (e) {\n  if (e instanceof SecurityError && e.message.includes('reserved SDK function name')) {\n    // extract the suggested rename from the error message\n  }\n  throw e;\n}","preventionTips":["Avoid using `workflow`, `node`, `trigger`, `ifElse`, `switchCase`, `merge`, `splitInBatches`, `nextBatch`, `fromAi`, `nodeJson`, `sticky`, `placeholder`, `newCredential` as variable names","Prefix generic names: use `myNode`, `wfConfig`, `triggerNode` instead","Keep the ALLOWED_SDK_FUNCTIONS list handy when authoring SDK code"],"tags":["sdk-interpreter","naming","reserved-words","security"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}