{"record":{"id":"bf98865d79bf28e4","repo":"n8n-io/n8n","slug":"unsupported-syntax-unary-operator-node-operato","errorCode":null,"errorMessage":"Unsupported syntax: 'Unary operator ${node.operator}' is not allowed in SDK code","messagePattern":"Unsupported syntax: 'Unary operator (.+?)' is not allowed in SDK code","errorType":"exception","errorClass":"UnsupportedNodeError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts","lineNumber":603,"sourceCode":"\t/**\n\t * Visit a unary expression.\n\t */\n\tprivate visitUnaryExpression(node: ESTree.UnaryExpression): unknown {\n\t\tconst arg = this.evaluate(node.argument);\n\n\t\tswitch (node.operator) {\n\t\t\tcase '-':\n\t\t\t\treturn -(arg as number);\n\t\t\tcase '+':\n\t\t\t\treturn +(arg as number);\n\t\t\tcase '!':\n\t\t\t\treturn !arg;\n\t\t\tcase 'typeof':\n\t\t\t\treturn typeof arg;\n\t\t\tcase 'void':\n\t\t\t\treturn undefined;\n\t\t\tdefault:\n\t\t\t\tthrow new UnsupportedNodeError(\n\t\t\t\t\t`Unary operator ${node.operator}`,\n\t\t\t\t\tnode.loc ?? undefined,\n\t\t\t\t\tthis.sourceCode,\n\t\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Visit a binary expression.\n\t */\n\tprivate visitBinaryExpression(node: ESTree.BinaryExpression): unknown {\n\t\tconst left = this.evaluate(node.left as ESTree.Expression);\n\t\tconst right = this.evaluate(node.right);\n\n\t\tswitch (node.operator) {\n\t\t\tcase '+':\n\t\t\t\tif (typeof left === 'string' || typeof right === 'string') {\n\t\t\t\t\treturn String(left) + String(right);","sourceCodeStart":585,"sourceCodeEnd":621,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/ast-interpreter/interpreter.ts#L585-L621","documentation":"The interpreter supports five unary operators: `-` (negation), `+` (coercion), `!` (logical NOT), `typeof`, and `void`. All other unary operators throw `UnsupportedNodeError` at interpreter.ts:603. This includes `~` (bitwise NOT) and `delete` — the former is rarely needed and the latter mutates state.","triggerScenarios":"Writing `~x` (bitwise NOT), `~~x` (truncate trick), or `delete obj.prop` in SDK code. The switch at interpreter.ts:591 only has cases for `-`, `+`, `!`, `typeof`, `void`.","commonSituations":"Using bitwise NOT for numeric tricks (`~~3.7` for truncation); `delete` for property removal; porting low-level or performance-oriented JS.","solutions":["For `~`/bitwise: move to a Code node or n8n expression; use `Math.floor` or arithmetic","For `delete`: use property reassignment to undefined (`obj.prop = undefined`) or move to Code node","Restructure the expression to use only `-`, `+`, `!`, `typeof`"],"exampleFix":"// before\nconst truncated = ~~3.7;\n\n// after\n// (bitwise NOT not supported; move to Code node or use arithmetic)\nconst truncated = 3 < 0 ? -Math.floor(-3) : Math.floor(3); // in a Code node\n// In SDK code, avoid truncation entirely","handlingStrategy":"validation","validationCode":"const ALLOWED_UNARY = new Set(['-', '+', '!', 'typeof', 'void']);\n\nfunction findBadUnaryOperators(code: string): string[] {\n  const ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module' });\n  const bad: string[] = [];\n  walk(ast, (node) => {\n    if (node.type === 'UnaryExpression' && !ALLOWED_UNARY.has(node.operator)) {\n      bad.push(node.operator);\n    }\n  });\n  return bad;\n}","typeGuard":null,"tryCatchPattern":"import { UnsupportedNodeError } from '@n8n/workflow-sdk/ast-interpreter/errors';\n\ntry {\n  interpretSDKCode(sdkCode, sdkFunctions);\n} catch (e) {\n  if (e instanceof UnsupportedNodeError && e.message.includes('Unary operator')) {\n    // show allowed operators and suggest alternatives\n  }\n  throw e;\n}","preventionTips":["Allowed unary operators: `-`, `+`, `!`, `typeof`, `void`","Avoid bitwise NOT (`~`) and `delete` in SDK code","For truncation, use a Code node instead of `~~`"],"tags":["sdk-interpreter","unary-operator","bitwise","delete"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}