denoland/deno · error · TypeError
Invalid WebAssembly content type
Error message
Invalid WebAssembly content type
What it means
WebAssembly.instantiateStreaming() and compileStreaming() require the response's Content-Type header to be exactly application/wasm (compared lowercased, so any parameter suffix such as '; charset=utf-8' fails). Deno exempts file:// URLs because local file fetches carry no Content-Type.
Solutions
- Configure the server/CDN to send exactly 'Content-Type: application/wasm' for .wasm files, with no parameters
- If you cannot change the header, use the non-streaming API: WebAssembly.instantiate(await (await fetch(url)).arrayBuffer())
- For local files use fetch('file:///...wasm') (exempt from the check) or Deno.readFile + non-streaming compile
Example fix
// before
const mod = await WebAssembly.instantiateStreaming(fetch("/app.wasm"));
// after (server header cannot be fixed)
const res = await fetch("/app.wasm");
const mod = await WebAssembly.instantiate(await res.arrayBuffer()); Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(url);
const ct = (res.headers.get("content-type") ?? "").toLowerCase();
if (ct === "application/wasm") {
result = await WebAssembly.instantiateStreaming(res);
} else {
result = await WebAssembly.instantiate(await res.arrayBuffer());
} Try / catch
try {
mod = await WebAssembly.instantiateStreaming(res);
} catch (err) {
if (err instanceof TypeError && err.message === "Invalid WebAssembly content type") {
mod = await WebAssembly.instantiate(await res.arrayBuffer());
} else throw err;
} Prevention
- Verify with curl -I that .wasm responses send exactly application/wasm
- Keep the Content-Type header free of parameters like charset
- Default to the buffer-based (non-streaming) compile when you do not control headers
When it happens
Trigger: WebAssembly.instantiateStreaming(fetch('/module.wasm')) when the server replies with application/octet-stream, text/plain, application/wasm; charset=utf-8, or omits the header; serving .wasm from a dev server without a wasm mime mapping; passing a blob: or data: response lacking the header.
Common situations: Static file servers (python -m http.server, naive SPA hosts) that default .wasm to octet-stream; CDN misconfiguration; middleware rewriting headers and adding charset; fixtures served from memory without headers.
Related errors
- Body can not be decoded as form data
- Cannot construct MultipartParser: multipart/form-data must…
- Cannot turn into form data: missing boundary parameter in…
- Failed to receive WebAssembly content: HTTP status code
- Missing content type
AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20).
Data as JSON: /api/errors/fa704bd53dabe5db.
Report an issue: GitHub.
Appendix: source
Thrown at ext/fetch/26_fetch.js:1028
try {
const res = webidl.converters["Response"](
source,
"Failed to execute 'WebAssembly.compileStreaming'",
"Argument 1",
);
// 2.3.
// The spec is ambiguous here, see
// https://github.com/WebAssembly/spec/issues/1138. The WPT tests expect
// the raw value of the Content-Type attribute lowercased. We ignore this
// for file:// because file fetches don't have a Content-Type.
if (!StringPrototypeStartsWith(res.url, "file://")) {
const contentType = res.headers.get("Content-Type");
if (
typeof contentType !== "string" ||
StringPrototypeToLowerCase(contentType) !== "application/wasm"
) {
throw new TypeError("Invalid WebAssembly content type");
}
}
// 2.5.
if (!res.ok) {
throw new TypeError(
`Failed to receive WebAssembly content: HTTP status code ${res.status}`,
);
}
// Pass the resolved URL to v8.
op_wasm_streaming_set_url(rid, res.url);
if (res.body !== null) {
// 2.6.
// Rather than consuming the body as an ArrayBuffer, this feeds each chunk
// to the streaming compiler as soon as it's available. Instead of reading
// the body chunk-by-chunk in JS and calling `op_wasm_streaming_feed` onceView on GitHub (pinned to a961cdec3b)