{"record":{"id":"4290a8be28f2274c","repo":"Zie619/n8n-workflows","slug":"environment-not-supported-for-base64-encoding","errorCode":null,"errorMessage":"Environment not supported for Base64 encoding","messagePattern":"Environment not supported for Base64 encoding","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"workflows/Splitout/1993_Splitout_Code_Automation_Triggered.json","lineNumber":150,"sourceCode":"      ],\n      \"parameters\": {\n        \"mode\": \"runOnceForEachItem\",\n        \"jsCode\": \"let text = $json.data\\n\\ndelete $json.base64\\ndelete $json.binary\\n\\n\\n// Split by single newlines\\nconst lines = text.split('\\\\n')\\n\\n// Create an array to hold grouped subtitle entries\\nlet subtitleGroups = []\\nlet currentGroup = []\\n\\n// Process each line\\nfor (let i = 0; i < lines.length; i++) {\\n  const line = lines[i].trim()\\n  \\n  // If line is empty and we have content in currentGroup, \\n  // it's the end of a subtitle entry\\n  if (line === '' && currentGroup.length > 0) {\\n    subtitleGroups.push(currentGroup.join('\\\\n'))\\n    currentGroup = []\\n  } \\n  // If line is not empty, add to current group\\n  else if (line !== '') {\\n    currentGroup.push(line)\\n  }\\n}\\n\\n// Add the last group if it has content\\nif (currentGroup.length > 0) {\\n  subtitleGroups.push(currentGroup.join('\\\\n'))\\n}\\n\\n// Remove any quotes at the beginning and end of the first and last entries\\nif (subtitleGroups.length > 0) {\\n  subtitleGroups[0] = subtitleGroups[0].replace(/^\\\"/, '')\\n  subtitleGroups[subtitleGroups.length - 1] = subtitleGroups[subtitleGroups.length - 1].replace(/\\\"$/, '')\\n}\\n\\n// Store the result\\n$input.item.json.txt = subtitleGroups\\n\\nreturn $input.item;\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"08215886-05f6-4ecc-9c1f-55c0e4cb6194\",\n      \"name\": \"Generate Binary\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        1180,\n        340\n      ],\n      \"parameters\": {\n        \"mode\": \"runOnceForEachItem\",\n        \"jsCode\": \"function encodeBase64(text) {\\n  try {\\n    // For browser environments\\n    if (typeof window !== 'undefined') {\\n      // First, create a UTF-8 encoded string\\n      const utf8String = encodeURIComponent(text)\\n        .replace(/%([0-9A-F]{2})/g, (_, hex) => {\\n          return String.fromCharCode(parseInt(hex, 16));\\n        });\\n      \\n      // Then encode to Base64\\n      return btoa(utf8String);\\n    } \\n    // For Node.js environments\\n    else if (typeof Buffer !== 'undefined') {\\n      return Buffer.from(text).toString('base64');\\n    }\\n    \\n    throw new Error('Environment not supported for Base64 encoding');\\n  } catch (error) {\\n    console.error('Error encoding to Base64:', error);\\n    return null;\\n  }\\n}\\n\\nlet data = encodeBase64($json.complete_text);\\n\\nconsole.log(data)\\n\\nlet file = $json.file\\n\\nfile.data = data;\\n\\nlet paddingCount = 0;\\nif (data.endsWith('==')) paddingCount = 2;\\nelse if (data.endsWith('=')) paddingCount = 1;\\n\\n// Calculate the decoded size (in bytes)\\nfile.size = Math.floor(data.length * 3 / 4) - paddingCount;\\n\\n\\nreturn file\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"\n    },\n    {\n      \"id\": \"299122c1-61d1-4ce4-81b9-ce15d22cd49c\",\n      \"name\": \"Prep Parts for Translate\",\n      \"type\": \"n8n-nodes-base.code\",\n      \"position\": [\n        1400,\n        140\n      ],\n      \"parameters\": {\n        \"mode\": \"runOnceForEachItem\",\n        \"jsCode\": \"function splitBySecondNewline(text) {\\n  // Find the position of the first newline\\n  const firstNewlinePos = text.indexOf('\\\\n');\\n  \\n  if (firstNewlinePos === -1) {\\n    return { firstPart: text, secondPart: '' }; // No newlines found\\n  }\\n  \\n  // Find the position of the second newline\\n  const secondNewlinePos = text.indexOf('\\\\n', firstNewlinePos + 1);\\n  \\n  if (secondNewlinePos === -1) {\\n    return { firstPart: text, secondPart: '' }; // Only one newline found\\n  }\\n  \\n  // Split the string at the second newline\\n  const firstPart = text.substring(0, secondNewlinePos);\\n  const secondPart = text.substring(secondNewlinePos + 1);\\n  \\n  return { firstPart, secondPart };\\n}\\n\\nlet lang = $('Receive SRT File to Translate').first().json['Translate to Language']\\n\\nreturn {\\n  parts: splitBySecondNewline($json.txt),\\n  language: lang\\n}\"\n      },\n      \"typeVersion\": 2,\n      \"notes\": \"This code node performs automated tasks as part of the workflow.\"","sourceCodeStart":132,"sourceCodeEnd":168,"githubUrl":"https://github.com/Zie619/n8n-workflows/blob/94007c1445d9258a7da116646b79473e7c7c3282/workflows/Splitout/1993_Splitout_Code_Automation_Triggered.json#L132-L168","documentation":"Thrown inside encodeBase64() in the 'Generate Binary' Code node when neither window nor Buffer is defined in the runtime. n8n Code nodes run in a Node.js sandbox where window is undefined; on versions/configurations using the isolated task runner (n8n 1.x with N8N_RUNNERS_ENABLED) Buffer may not be exposed the way the old vm2 sandbox exposed it, so both branches fail and the fallback throw fires. The node base64-encodes $json.complete_text and patches it into a binary file descriptor (data, size).","triggerScenarios":"Upgrade to n8n >= 1.6 with the external task runner where Buffer is not available in the Code node sandbox; running the code in a preview/browser harness where neither btoa nor Buffer exists; strict sandbox settings stripping Node built-ins.","commonSituations":"n8n version migration (vm2 sandbox -> task runner) breaking Buffer access; copied browser code with an environment sniff that never matches the actual runtime. Note a secondary bug: the catch block returns null, so after this error data is null and data.endsWith('==') throws a TypeError 'Cannot read properties of null' — the reported message may be masked.","solutions":["On modern n8n the Code node does expose Buffer via the built-in require/builtins — remove the window branch and call Buffer.from($json.complete_text).toString('base64') directly.","If Buffer is genuinely unavailable, use the sandbox-safe pure-JS path: Buffer is available as a global in the default runner; otherwise route through a 'Move Binary Data'/'Convert to File' node instead of hand-encoding.","Fix the null-swallowing catch: let the error propagate (remove the try/catch or rethrow) so the real failure is visible instead of the downstream TypeError.","Pin the n8n version and test the Code node after upgrades; env-detection code rots."],"exampleFix":"// before\nfunction encodeBase64(text) {\n  try {\n    if (typeof window !== 'undefined') { /* btoa path */ }\n    else if (typeof Buffer !== 'undefined') { return Buffer.from(text).toString('base64'); }\n    throw new Error('Environment not supported for Base64 encoding');\n  } catch (error) {\n    console.error('Error encoding to Base64:', error);\n    return null; // hides the failure, causes TypeError later\n  }\n}\nlet data = encodeBase64($json.complete_text);\n\n// after - single Node.js path, fail fast\nconst data = Buffer.from($json.complete_text, 'utf-8').toString('base64');\nif (!data) {\n  throw new Error('Base64 encoding produced empty output');\n}","handlingStrategy":"type-guard","validationCode":"// Fail fast if the runtime cannot encode, instead of the window/Buffer sniff:\nconst data = Buffer.from(String($json.complete_text ?? ''), 'utf-8').toString('base64');\nif (!data) {\n  throw new Error('Base64 encoding produced empty output');\n}","typeGuard":"const canBase64 = () => typeof Buffer !== 'undefined' || typeof btoa === 'function';\n// usage: if (!canBase64()) throw new Error('Runtime cannot base64-encode; use a Convert to File node instead');","tryCatchPattern":"try {\n  const data = Buffer.from($json.complete_text, 'utf-8').toString('base64');\n  file.data = data;\n} catch (e) {\n  throw new Error(`Base64 encode failed for file ${file?.fileName ?? '?'}: ${e.message}`);\n}","preventionTips":["Never return null from an encode helper to 'handle' failure — rethrow so the failure point is honest.","After any n8n upgrade, smoke-test Code nodes that touch Buffer/require; sandbox capabilities change between runner versions.","Prefer built-in binary nodes ('Move Binary Data'/'Convert to File') over hand-rolled base64 in Code nodes."],"tags":["n8n","code-node","base64","sandbox","task-runner","runtime-environment"],"backgroundTag":null,"analyzedSha":"94007c1445d9258a7da116646b79473e7c7c3282","analyzedAt":"2026-08-15T04:10:37.591Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}