denoland/deno · error · TypeError

ERR_UNKNOWN_ENCODING

ERR_UNKNOWN_ENCODING

Error message

Unknown encoding: ${encoding}

What it means

_lazyInitCipherDecoder builds a StringDecoder for the output encoding requested by update(data, inputEnc, outputEnc) or final(encoding). normalizeEncoding() must map the string to a known encoding or ERR_UNKNOWN_ENCODING is thrown; only encodings StringDecoder supports are valid (utf8/utf-8, utf16le, latin1/binary, ascii, base64, base64url, hex). Passing 'buffer' skips decoder creation entirely.

Source

Thrown at ext/node/polyfills/internal/crypto/cipher.ts:423

  if (outputEncoding !== "buffer") {
    return this._decoder!.write(output);
  }

  return output;
};

function _lazyInitCipherDecoder(self: any, encoding: string) {
  if (encoding === "buffer") {
    return;
  }

  const normalizedEncoding = normalizeEncoding(encoding);
  self._decoder ||= new StringDecoder(normalizedEncoding);

  if (self._decoder.encoding !== normalizedEncoding) {
    if (normalizedEncoding === undefined) {
      throw new ERR_UNKNOWN_ENCODING(encoding);
    }
    assert(false, "Cannot change encoding");
  }
}

/** Caches data and output the chunk of multiple of 16.
 * Used by CBC, ECB modes of block ciphers */
class BlockModeCache {
  cache: Uint8Array;
  blockSize: number;
  // The last chunk can be padded when decrypting.
  #lastChunkIsNonZero: boolean;

  constructor(lastChunkIsNotZero = false, blockSize = 16) {
    this.cache = new Uint8Array(0);
    this.blockSize = blockSize;
    this.#lastChunkIsNonZero = lastChunkIsNotZero;
  }

View on GitHub (pinned to 9ad36f7a2c)

Solutions

  1. Use exact supported names: 'utf8', 'utf16le', 'latin1', 'ascii', 'base64', 'base64url', 'hex'.
  2. Omit the encoding or pass 'buffer' when you want Buffer output rather than a string.
  3. Validate encodings against an allow-list before calling update()/final().

Example fix

// before
const s = cipher.update(data, 'utf8', 'utf-16'); // ERR_UNKNOWN_ENCODING

// after
const s = cipher.update(data, 'utf8', 'utf16le'); // or 'utf8' / 'base64' / 'buffer'
Defensive patterns

Strategy: validation

Validate before calling

const STRING_DECODER_ENCODINGS = new Set([
  'utf8','utf-8','utf16le','utf-16le','latin1','binary','ascii','base64','base64url','hex',
]);
function assertEncoding(enc: string): void {
  if (enc !== 'buffer' && !STRING_DECODER_ENCODINGS.has(enc.toLowerCase()))
    throw new TypeError(`Unknown encoding: ${enc}`);
}

Try / catch

try { s = cipher.final(enc); } catch (e) { if (e.code === 'ERR_UNKNOWN_ENCODING') { s = cipher.final('buffer').toString(enc === 'base64-url' ? 'base64url' : 'utf8'); } else throw e; }

Prevention

When it happens

Trigger: cipher.update(data, 'utf8', 'base62') (made-up name); cipher.final('base64-url') instead of 'base64url'; an undefined encoding variable after refactor; swapping the inputEncoding and outputEncoding arguments.

Common situations: Encoding names read from config or user input; typos like 'hex ' with trailing space or 'utf-16' instead of 'utf16le'; code ported from iconv-style libraries with different encoding aliases.

Related errors


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