vitejs/vite · error · Error
Failed to decode base64-encoded data URL, Buffer and atob…
Error message
Failed to decode base64-encoded data URL, Buffer and atob are not supported
What it means
wasmHelper decodes a base64 'data:' URL by trying Node's Buffer.from first, then the global atob. If neither is available it throws, because it cannot turn the data URL into bytes for WebAssembly.instantiate. This path runs client-side when a wasm import resolves to an inline data URL.
Solutions
- Run the wasm import in an environment that provides atob (modern browsers) or Buffer (Node).
- Polyfill atob (or Buffer) in the target runtime before the wasm module loads.
- Avoid inlining the wasm (so the data-URL branch is not taken) — configure assets so the wasm is emitted as a file and fetched via URL instead.
- If using a custom JS runtime for SSR/tests, enable its fetch/Buffer shims.
Example fix
// before — runtime lacks both Buffer and atob
// after — polyfill atob before app code
import { atobPolyfill } from './atob-polyfill'
globalThis.atob = globalThis.atob || atobPolyfill Defensive patterns
Strategy: type-guard
Validate before calling
// Ensure decode primitives exist before app boots
function assertBase64Decoders() {
if (typeof Buffer !== 'function' && typeof atob !== 'function') {
throw new Error('Polyfill Buffer or atob before loading wasm data URLs')
}
}
assertBase64Decoders() Type guard
function hasBase64Decoder(): boolean {
return (typeof Buffer === 'function' && typeof Buffer.from === 'function') || typeof atob === 'function'
} Prevention
- Target modern browsers (they have atob) or Node (Buffer) when using inlined wasm.
- Polyfill atob in custom runtimes.
- Avoid wasm inlining via assetsInlineLimit: 0 if your runtime lacks decoders.
When it happens
Trigger: Importing a .wasm module that gets inlined as a base64 data URL, in a runtime that has neither Buffer (Node-only) nor atob (very old or non-standard JS envs). The wasmHelper is shipped as a string and evaluated in the target runtime, so it depends on those globals being present.
Common situations: Embedding Vite-built wasm in a restricted/legacy runtime, a custom SSR environment without Node globals, or a test runner that strips globals. Browsers have atob, so this mostly bites non-browser embedded runtimes.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Could not resolve " " imported by " ". Is it installed?
- Failed to parse WASM file
- FetchableDevEnvironment requires a global `Request` and…
- Vite module runner has been closed.
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/2a330175fe51f01b.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vite/src/node/plugins/wasm.ts:54
...wasmCompileOptions.builtins.map((name) => `wasm:${name}`),
wasmCompileOptions.importedStringConstants,
])
const wasmHelper = async (opts = {}, url: string) => {
let result
if (url.startsWith('data:')) {
const urlContent = url.replace(/^data:.*?base64,/, '')
let bytes
if (typeof Buffer === 'function' && typeof Buffer.from === 'function') {
bytes = Buffer.from(urlContent, 'base64')
} else if (typeof atob === 'function') {
const binaryString = atob(urlContent)
bytes = new Uint8Array(binaryString.length)
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i)
}
} else {
throw new Error(
'Failed to decode base64-encoded data URL, Buffer and atob are not supported',
)
}
result = await WebAssembly.instantiate(bytes, opts, wasmCompileOptions)
} else {
result = await instantiateFromUrl(url, opts)
}
return result.instance
}
const wasmHelperCode = wasmHelper.toString()
const instantiateFromUrl = async (url: string, opts?: WebAssembly.Imports) => {
// https://github.com/mdn/webassembly-examples/issues/5
// WebAssembly.instantiateStreaming requires the server to provide the
// correct MIME type for .wasm files, which unfortunately doesn't work for
// a lot of static file servers, so we just work around it by getting the
// raw buffer.View on GitHub (pinned to b4d66fee14)