denoland/deno · error · NodeError

ERR_STRING_TOO_LONG

ERR_STRING_TOO_LONG

Error message

Cannot create a string longer than 0x${maxStringLengthHex} characters

What it means

Thrown by Deno's node:string_decoder polyfill when a single conversion would produce a string longer than V8's MAX_STRING_LENGTH (about 0x1fffffe8, roughly 536.8 million characters). bufferToString() computes the requested span (end - start, defaulting to the whole buffer) and refuses the conversion up front, because V8 cannot allocate a JS string that large. Node.js throws the same ERR_STRING_TOO_LONG guard when creating strings from oversized buffers.

Source

Thrown at ext/node/polyfills/string_decoder.ts:118

        isTA
          ? TypedArrayPrototypeGetBuffer(buf)
          : DataViewPrototypeGetBuffer(buf),
        isTA
          ? TypedArrayPrototypeGetByteOffset(buf)
          : DataViewPrototypeGetByteOffset(buf),
        isTA
          ? TypedArrayPrototypeGetByteLength(buf)
          : DataViewPrototypeGetByteLength(buf),
      ),
    );
  }
}

const maxStringLengthHex = NumberPrototypeToString(MAX_STRING_LENGTH, 16);
function bufferToString(buf, encoding, start, end) {
  const len = (end ?? buf.length) - (start ?? 0);
  if (len > MAX_STRING_LENGTH) {
    throw new NodeError(
      "ERR_STRING_TOO_LONG",
      `Cannot create a string longer than 0x${maxStringLengthHex} characters`,
    );
  }
  // deno-lint-ignore deno-internal/prefer-primordials -- buf is a Buffer; Buffer.prototype.toString(encoding) is not String.prototype.toString
  return buf.toString(encoding, start, end);
}

const kBufferedBytes = Symbol("bufferedBytes");
const kMissingBytes = Symbol("missingBytes");

function decode(buf) {
  const enc = this.enc;

  let bufIdx = 0;
  let bufEnd = buf.length;

  let prepend = "";

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Decode incrementally: feed the StringDecoder fixed-size chunks (e.g. 1 MiB) with decoder.write() as data arrives, then decoder.end() at the end — partial multi-byte characters at chunk edges are buffered correctly
  2. Stream the source instead of buffering: for await (const chunk of fs.createReadStream(path)) text += decoder.write(chunk)
  3. If you already hold one huge buffer, loop over subarray(i, i + MAX) slices and decode each slice separately
  4. For base64/hex input, convert in chunks and avoid materializing the fully decoded output as one JS string at all

Example fix

// before
const text = new StringDecoder('utf8').end(fs.readFileSync('huge.bin'));

// after
const dec = new StringDecoder('utf8');
let text = '';
for await (const chunk of fs.createReadStream('huge.bin')) {
  text += dec.write(chunk);
}
text += dec.end();
Defensive patterns

Strategy: validation

Validate before calling

// V8 max string length guard (matches MAX_STRING_LENGTH, ~2**29 - 24)
const MAX_STRING = 2 ** 29 - 24;

function decodeSafe(decoder, buf) {
  if (buf.length <= MAX_STRING) {
    return decoder.write(buf) + decoder.end();
  }
  let out = '';
  for (let i = 0; i < buf.length; i += MAX_STRING) {
    out += decoder.write(buf.subarray(i, i + MAX_STRING));
  }
  return out + decoder.end();
}

Try / catch

try {
  text = decoder.end(hugeBuf);
} catch (err) {
  if (err?.code === 'ERR_STRING_TOO_LONG') {
    // fall back to chunked decoding
    text = decodeSafe(decoder, hugeBuf);
  } else {
    throw err;
  }
}

Prevention

When it happens

Trigger: Calling new StringDecoder(encoding).write(buf) or .end(buf) with a Buffer/TypedArray whose length (or end-start span) exceeds MAX_STRING_LENGTH: decoding a multi-hundred-MB file read with fs.readFileSync in one call, or accumulating network chunks into one giant buffer before decoding it as a single string.

Common situations: Reading whole large files (logs, dumps, media) into memory and decoding in one shot; merging streamed chunks into a single buffer before conversion; processing very large base64/hex payloads in one piece; test fixtures that accidentally reference huge binaries.

Related errors


AI-assisted analysis of denoland/deno@9ad36f7a2c (2026-08-20). Data as JSON: /api/errors/c0be4e2140f73df5. Report an issue: GitHub.