{"record":{"id":"59ff33436c4106df","repo":"clockworklabs/SpacetimeDB","slug":"the-encoding-label-provided-is-invalid","errorCode":null,"errorMessage":"The encoding label provided is invalid","messagePattern":"The encoding label provided is invalid","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"crates/core/src/host/v8/builtins/text_encoding.js","lineNumber":32,"sourceCode":"  encode(input = '') {\n    return utf8_encode(input);\n  }\n};\n\nglobalThis.TextDecoder = class TextDecoder {\n  /** @type {string} */\n  #encoding;\n\n  /** @type {boolean} */\n  #fatal;\n\n  /**\n   * @argument {string} label\n   * @argument {any} options\n   */\n  constructor(label = 'utf-8', options = {}) {\n    if (label !== 'utf-8') {\n      throw new RangeError('The encoding label provided is invalid');\n    }\n    this.#encoding = label;\n    this.#fatal = !!options.fatal;\n    if (options.ignoreBOM) {\n      throw new TypeError(\"Option 'ignoreBOM' not supported\");\n    }\n  }\n\n  get encoding() {\n    return this.#encoding;\n  }\n  get fatal() {\n    return this.#fatal;\n  }\n  get ignoreBOM() {\n    return false;\n  }\n","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/clockworklabs/SpacetimeDB/blob/524b4487d949b61a07d4f39c862d1290259dfd20/crates/core/src/host/v8/builtins/text_encoding.js#L14-L50","documentation":"The SpacetimeDB V8 host installs its own TextEncoder/TextDecoder polyfill (crates/core/src/host/v8/builtins/text_encoding.js) that implements only UTF-8. Unlike the WHATWG Encoding Standard, which accepts dozens of labels and normalizes them, this polyfill compares the label as the exact string 'utf-8' and throws a RangeError for anything else.","triggerScenarios":"Constructing new TextDecoder('utf-16le'), new TextDecoder('windows-1252'), or any non-'utf-8' label; also labels browsers would normalize, such as 'utf8' (no dash), 'UTF-8' (uppercase), or 'unicode-1-1-utf-8', because the raw string is compared.","commonSituations":"Decoding payloads encoded with a legacy charset; porting browser or Node code that passes a shorthand label like 'utf8'; receiving data from systems that emit UTF-16 and trying to decode it in-module.","solutions":["Pass no label at all — the constructor defaults to 'utf-8': new TextDecoder()","Normalize labels before constructing: lowercase and ensure the dash form 'utf-8'","For non-UTF-8 data, transcode it to UTF-8 on the client/broker side before it reaches the module"],"exampleFix":"// before\nconst dec = new TextDecoder(label); // RangeError unless label === 'utf-8'\n\n// after\nconst dec = new TextDecoder(label === 'utf8' || label === 'UTF-8' ? 'utf-8' : label);","handlingStrategy":"validation","validationCode":"const SUPPORTED = 'utf-8';\nfunction normalizeLabel(label?: string): string {\n  const norm = (label ?? 'utf-8').trim().toLowerCase().replace(/^utf8$/, 'utf-8');\n  if (norm !== SUPPORTED) {\n    throw new RangeError(`Encoding '${label}' is not supported; only utf-8 is. Transcode the data first.`);\n  }\n  return norm;\n}\nconst dec = new TextDecoder(normalizeLabel(userLabel));","typeGuard":"function isSupportedEncodingLabel(label: string): boolean {\n  return label.trim().toLowerCase() === 'utf-8' || label.trim().toLowerCase() === 'utf8';\n}","tryCatchPattern":"try {\n  const dec = new TextDecoder(label);\n} catch (e) {\n  if (e instanceof RangeError && /encoding label/.test(e.message)) {\n    // fall back to utf-8 only if the payload is known to be UTF-8\n    return new TextDecoder();\n  }\n  throw e;\n}","preventionTips":["Omit the label argument unless you truly need to vary encodings","Enforce UTF-8 at every boundary (clients, brokers) so modules never see other encodings","Centralize decoder construction in one helper so the label constraint is checked in one place"],"tags":["javascript","textdecoder","encoding","utf-8","polyfill","v8"],"backgroundTag":"unsupported-encoding-label","analyzedSha":"524b4487d949b61a07d4f39c862d1290259dfd20","analyzedAt":"2026-08-16T23:58:54.611Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}