{"record":{"id":"812160fb6ba842a8","repo":"n8n-io/n8n","slug":"code-nested-template-literal","errorCode":"CODE_NESTED_TEMPLATE_LITERAL","errorMessage":"${namePrefix}Code node uses nested template literals, which often break after save. Build multi-line strings with arrays joined by a runtime separator, e.g. `const LF = String.fromCharCode(10); return lines.join(LF);`.","messagePattern":"(.+?)Code node uses nested template literals, which often break after save\\. Build multi-line strings with arrays joined by a runtime separator, e\\.g\\. `const LF = String\\.fromCharCode\\(10\\); return lines\\.join\\(LF\\);`\\.","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"packages/@n8n/workflow-sdk/src/lint/code-node/js.ts","lineNumber":209,"sourceCode":"\tif (options.mode === 'runOnceForEachItem' && disallowedInputMethod !== undefined) {\n\t\tissues.push(\n\t\t\tlintIssue({\n\t\t\t\tcode: 'CODE_MODE_API_MISUSE',\n\t\t\t\tmessage:\n\t\t\t\t\t`${namePrefix}uses mode: 'runOnceForEachItem' but calls $input.${disallowedInputMethod}(). ` +\n\t\t\t\t\t`$input.${disallowedInputMethod}() is only available in runOnceForAllItems (the default). ` +\n\t\t\t\t\t'Switch mode to runOnceForAllItems, or use $input.item / $json for per-item work.',\n\t\t\t\tlintTarget: 'jsCode',\n\t\t\t\tnodeName: options.nodeName,\n\t\t\t\tparameterPath: 'jsCode',\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (hasNestedTemplateLiteral(ast)) {\n\t\tissues.push(\n\t\t\tlintIssue({\n\t\t\t\tcode: 'CODE_NESTED_TEMPLATE_LITERAL',\n\t\t\t\tmessage:\n\t\t\t\t\t`${namePrefix}Code node uses nested template literals, which often break after save. ` +\n\t\t\t\t\t'Build multi-line strings with arrays joined by a runtime separator, e.g. ' +\n\t\t\t\t\t'`const LF = String.fromCharCode(10); return lines.join(LF);`.',\n\t\t\t\tlintTarget: 'jsCode',\n\t\t\t\tnodeName: options.nodeName,\n\t\t\t\tparameterPath: 'jsCode',\n\t\t\t}),\n\t\t);\n\t}\n\n\treturn issues;\n}\n\n/** @deprecated Use lintJsCode — nested templates are detected via AST there. */\nexport function hasNestedTemplateLiterals(jsCode: string): boolean {\n\tconst ast = parseJs(jsCode);\n\treturn ast ? hasNestedTemplateLiteral(ast) : false;","sourceCodeStart":191,"sourceCodeEnd":227,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/workflow-sdk/src/lint/code-node/js.ts#L191-L227","documentation":"CODE_NESTED_TEMPLATE_LITERAL is a lint issue. hasNestedTemplateLiteral() walks the AST and reports any TemplateLiteral that contains another TemplateLiteral inside its expression slots. These nested backtick interpolations are known to break after n8n serializes/deserializes the workflow.","triggerScenarios":"Code like `${`inner ${value}`}` or `a ${`b ${c}`}` inside jsCode — a backtick template nested inside another backtick template's ${ }.","commonSituations":"LLM builds a multi-line string with nested template interpolation; developer composes a prompt string by nesting templates; concatenating dynamic fragments inside one outer template.","solutions":["Build the multi-line string from an array joined by a runtime separator, e.g. const LF = String.fromCharCode(10); return lines.join(LF);","Flatten the nested template into a single-level template using intermediate variables.","Move complex string building into a Code node and pass the result forward."],"exampleFix":"// before (Code node jsCode)\nreturn `header\n${rows.map((r) => `${r.id},${r.name}`).join('\\n')}`;\n// after\nconst LF = String.fromCharCode(10);\nconst body = rows.map((r) => r.id + ',' + r.name).join(LF);\nreturn ['header', body].join(LF);","handlingStrategy":"validation","validationCode":"import { lintJsCode } from '@n8n/workflow-sdk/lint/code-node/js';\nconst issues = lintJsCode(jsCode, { mode });\nif (issues.some((i) => i.code === 'CODE_NESTED_TEMPLATE_LITERAL')) {\n  throw new Error('jsCode has nested template literals; rebuild the string via array join.');\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Avoid backtick templates inside ${ } of another backtick template.","Build multi-line strings with arrays joined by String.fromCharCode separators.","Run lintJsCode on generated Code node bodies before saving."],"tags":["lint","code-node","sdk"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}