evanw/esbuild · critical · Error
No UTF-8 codec found
Error message
No UTF-8 codec found
What it means
esbuild's stdio protocol layer needs to encode/decode UTF-8 between JS and the Go binary. lib/shared/stdio_protocol.ts:414-433 probes for TextEncoder/TextDecoder first (modern browsers and Node ≥12), then falls back to Buffer (Node 10), and if neither global is present, throws 'No UTF-8 codec found'. This is an environment-capability guard: the host JS runtime lacks both the Web TextCodec API and Node's Buffer, so esbuild cannot marshal strings.
Source
Thrown at lib/shared/stdio_protocol.ts:433
let encoder = new TextEncoder()
let decoder = new TextDecoder()
encodeUTF8 = text => encoder.encode(text)
decodeUTF8 = bytes => decoder.decode(bytes)
encodeInvariant = 'new TextEncoder().encode("")'
}
// For node 10.x
else if (typeof Buffer !== 'undefined') {
encodeUTF8 = text => Buffer.from(text)
decodeUTF8 = bytes => {
let { buffer, byteOffset, byteLength } = bytes
return Buffer.from(buffer, byteOffset, byteLength).toString()
}
encodeInvariant = 'Buffer.from("")'
}
else {
throw new Error('No UTF-8 codec found')
}
// Throw an error early if this isn't true. The test framework called "Jest"
// has some bugs regarding this edge case, and letting esbuild proceed further
// leads to confusing errors that make it seem like esbuild itself has a bug.
if (!(encodeUTF8('') instanceof Uint8Array))
throw new Error(`Invariant violation: "${encodeInvariant} instanceof Uint8Array" is incorrectly false
This indicates that your JavaScript environment is broken. You cannot use
esbuild in this environment because esbuild relies on this invariant. This
is not a problem with esbuild. You need to fix your environment instead.
`)
export function readUInt32LE(buffer: Uint8Array, offset: number): number {
return (
buffer[offset++] |
(buffer[offset++] << 8) |
(buffer[offset++] << 16) |View on GitHub (pinned to 6ff1d8b0d8)
Solutions
- Provide a TextEncoder/TextDecoder polyfill (e.g. 'fast-text-encoding', 'text-encoding') before importing esbuild.
- Run in a modern Node (≥12) or any current browser where TextEncoder is global.
- If you control the runtime, ensure the global TextEncoder constructor is defined on globalThis.
Example fix
// before — esbuild imported in an engine without TextEncoder import * as esbuild from 'esbuild'; // throws: No UTF-8 codec found // after — polyfill first import 'fast-text-encoding'; import * as esbuild from 'esbuild';
Defensive patterns
Strategy: validation
Validate before calling
function ensureUtf8Codec() {
if (typeof TextEncoder === 'undefined' && typeof Buffer === 'undefined') {
throw new Error('This environment has no UTF-8 codec; import a TextEncoder polyfill before esbuild.');
}
}
ensureUtf8Codec();
import 'esbuild'; Type guard
function hasUtf8Codec(): boolean {
return typeof TextEncoder !== 'undefined' && typeof TextDecoder !== 'undefined'
|| typeof Buffer !== 'undefined';
} Prevention
- In embedded/legacy engines, import 'fast-text-encoding' before esbuild.
- Run esbuild under Node ≥12 or any modern browser.
- If you control the runtime, expose globalThis.TextEncoder.
When it happens
Trigger: Running esbuild in a stripped-down JS engine that defines neither TextEncoder nor Buffer (some embedded JS runtimes, ancient browsers, or a polyfill-less environment). A bundler that tree-shook away a TextEncoder polyfill. Node started with --no-experimental-strip-types and a custom global setup that deleted Buffer.
Common situations: Edge/embedded JS engines (QuickJS, Hermes without textcodec polyfill). Older Internet Explorer without TextEncoder and without a Buffer shim. Test environments that sandbox globals.
Related errors
- Invariant violation: "${encodeInvariant} instanceof Uint8Arr
- Module not found in bundle: ${path}
- The "write" option is unavailable in this environment
- Cannot use the "watch" API in this environment
- Cannot use the "serve" API in this environment
AI-assisted analysis of evanw/esbuild@6ff1d8b0d8 (2026-08-03).
Data as JSON: /data/errors/83a8208a21485538.json.
Report an issue: GitHub.