{"record":{"id":"c28292cee95667d6","repo":"denoland/deno","slug":"err-unknown-encoding","errorCode":"ERR_UNKNOWN_ENCODING","errorMessage":"Unknown encoding: ${encoding}","messagePattern":"Unknown encoding: (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/node/polyfills/internal/crypto/cipher.ts","lineNumber":423,"sourceCode":"\n  if (outputEncoding !== \"buffer\") {\n    return this._decoder!.write(output);\n  }\n\n  return output;\n};\n\nfunction _lazyInitCipherDecoder(self: any, encoding: string) {\n  if (encoding === \"buffer\") {\n    return;\n  }\n\n  const normalizedEncoding = normalizeEncoding(encoding);\n  self._decoder ||= new StringDecoder(normalizedEncoding);\n\n  if (self._decoder.encoding !== normalizedEncoding) {\n    if (normalizedEncoding === undefined) {\n      throw new ERR_UNKNOWN_ENCODING(encoding);\n    }\n    assert(false, \"Cannot change encoding\");\n  }\n}\n\n/** Caches data and output the chunk of multiple of 16.\n * Used by CBC, ECB modes of block ciphers */\nclass BlockModeCache {\n  cache: Uint8Array;\n  blockSize: number;\n  // The last chunk can be padded when decrypting.\n  #lastChunkIsNonZero: boolean;\n\n  constructor(lastChunkIsNotZero = false, blockSize = 16) {\n    this.cache = new Uint8Array(0);\n    this.blockSize = blockSize;\n    this.#lastChunkIsNonZero = lastChunkIsNotZero;\n  }","sourceCodeStart":405,"sourceCodeEnd":441,"githubUrl":"https://github.com/denoland/deno/blob/9ad36f7a2cce60488e6ec52283efb32efddaf93a/ext/node/polyfills/internal/crypto/cipher.ts#L405-L441","documentation":"_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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Use exact supported names: 'utf8', 'utf16le', 'latin1', 'ascii', 'base64', 'base64url', 'hex'.","Omit the encoding or pass 'buffer' when you want Buffer output rather than a string.","Validate encodings against an allow-list before calling update()/final()."],"exampleFix":"// before\nconst s = cipher.update(data, 'utf8', 'utf-16'); // ERR_UNKNOWN_ENCODING\n\n// after\nconst s = cipher.update(data, 'utf8', 'utf16le'); // or 'utf8' / 'base64' / 'buffer'","handlingStrategy":"validation","validationCode":"const STRING_DECODER_ENCODINGS = new Set([\n  'utf8','utf-8','utf16le','utf-16le','latin1','binary','ascii','base64','base64url','hex',\n]);\nfunction assertEncoding(enc: string): void {\n  if (enc !== 'buffer' && !STRING_DECODER_ENCODINGS.has(enc.toLowerCase()))\n    throw new TypeError(`Unknown encoding: ${enc}`);\n}","typeGuard":null,"tryCatchPattern":"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; }","preventionTips":["Prefer 'buffer' output and call .toString(encoding) yourself with a validated name.","Use 'base64url' (not 'base64-url') and 'utf16le' (not 'utf-16').","Validate config-supplied encoding names against a constant set at startup."],"tags":["crypto","cipher","encoding","string-decoder","node-compat"],"backgroundTag":"unknown-encoding","analyzedSha":"9ad36f7a2cce60488e6ec52283efb32efddaf93a","analyzedAt":"2026-08-20T13:07:44.778Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}