Zie619/n8n-workflows · error · Error

Environment not supported for Base64 encoding

Error message

Environment not supported for Base64 encoding

What it means

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).

Source

Thrown at workflows/Splitout/1993_Splitout_Code_Automation_Triggered.json:150

      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "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;"
      },
      "typeVersion": 2,
      "notes": "This code node performs automated tasks as part of the workflow."
    },
    {
      "id": "08215886-05f6-4ecc-9c1f-55c0e4cb6194",
      "name": "Generate Binary",
      "type": "n8n-nodes-base.code",
      "position": [
        1180,
        340
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "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"
      },
      "typeVersion": 2,
      "notes": "This code node performs automated tasks as part of the workflow."
    },
    {
      "id": "299122c1-61d1-4ce4-81b9-ce15d22cd49c",
      "name": "Prep Parts for Translate",
      "type": "n8n-nodes-base.code",
      "position": [
        1400,
        140
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "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}"
      },
      "typeVersion": 2,
      "notes": "This code node performs automated tasks as part of the workflow."

View on GitHub (pinned to 94007c1445)

Solutions

  1. 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.
  2. 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.
  3. 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.
  4. Pin the n8n version and test the Code node after upgrades; env-detection code rots.

Example fix

// before
function encodeBase64(text) {
  try {
    if (typeof window !== 'undefined') { /* btoa path */ }
    else if (typeof Buffer !== 'undefined') { return Buffer.from(text).toString('base64'); }
    throw new Error('Environment not supported for Base64 encoding');
  } catch (error) {
    console.error('Error encoding to Base64:', error);
    return null; // hides the failure, causes TypeError later
  }
}
let data = encodeBase64($json.complete_text);

// after - single Node.js path, fail fast
const data = Buffer.from($json.complete_text, 'utf-8').toString('base64');
if (!data) {
  throw new Error('Base64 encoding produced empty output');
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Fail fast if the runtime cannot encode, instead of the window/Buffer sniff:
const data = Buffer.from(String($json.complete_text ?? ''), 'utf-8').toString('base64');
if (!data) {
  throw new Error('Base64 encoding produced empty output');
}

Type guard

const canBase64 = () => typeof Buffer !== 'undefined' || typeof btoa === 'function';
// usage: if (!canBase64()) throw new Error('Runtime cannot base64-encode; use a Convert to File node instead');

Try / catch

try {
  const data = Buffer.from($json.complete_text, 'utf-8').toString('base64');
  file.data = data;
} catch (e) {
  throw new Error(`Base64 encode failed for file ${file?.fileName ?? '?'}: ${e.message}`);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of Zie619/n8n-workflows@94007c1445 (2026-08-15). Data as JSON: /api/errors/4290a8be28f2274c. Report an issue: GitHub.