denoland/deno · error · TypeError
Failed to receive WebAssembly content: HTTP status code
Error message
Failed to receive WebAssembly content: HTTP status code ${res.status} What it means
After the Content-Type check, Deno's streaming WebAssembly compile verifies res.ok (status 200-299). A non-2xx reply (404, 401, 403, 500, an HTML error page) is not valid WebAssembly, so instantiateStreaming/compileStreaming throws a TypeError that includes the exact HTTP status received.
Solutions
- Check res.ok (or res.status) before passing the response to the streaming API
- Fix the URL / asset manifest to point at the real .wasm file
- Send the credentials or headers the endpoint requires (fetch(url, { credentials: 'include' }))
- Debug once by reading await res.text() of the failing response to see the error page
Example fix
// before
const { instance } = await WebAssembly.instantiateStreaming(fetch(url));
// after
const res = await fetch(url);
if (!res.ok) throw new Error(`wasm fetch failed: ${res.status}`);
const { instance } = await WebAssembly.instantiateStreaming(res); Defensive patterns
Strategy: validation
Validate before calling
const res = await fetch(url);
if (!res.ok) {
throw new Error(`wasm asset fetch failed: ${res.status} ${url}`);
}
const mod = await WebAssembly.instantiateStreaming(res); Try / catch
try {
mod = await WebAssembly.instantiateStreaming(res);
} catch (err) {
if (err instanceof TypeError && /HTTP status code/.test(err.message)) {
// wrong URL or auth: surface a clear deployment error
} else throw err;
} Prevention
- Always check res.ok before streaming a response into WebAssembly
- Load wasm paths from an asset manifest instead of hardcoding them
- Include required credentials/headers on protected CDNs
When it happens
Trigger: WebAssembly.instantiateStreaming(fetch(url)) where the server returns 404 (wrong path), 401/403 (authentication required by a gateway), 500, or a redirect chain ending in an error page.
Common situations: Deployed asset paths wrong after hashed filenames changed between releases; CDN access tokens expired; missing credentials: 'include' so the gateway returns 401; reverse proxy serving a maintenance page.
Related errors
- Invalid WebAssembly content type
- Blob URL fetch only supports GET method
- Body already consumed
- Body already consumed.
- Body can not be decoded as form data
AI-assisted analysis of denoland/deno@a961cdec3b (2026-08-20).
Data as JSON: /api/errors/6b380ca05fb34b62.
Report an issue: GitHub.
Appendix: source
Thrown at ext/fetch/26_fetch.js:1034
// 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` once
// per chunk, hand the underlying stream resource to `op_pipe` with the
// wasm streaming resource as the sink (`WasmStreamingResource` implements
// `Resource::write`), so a single async op pumps the bytes straight into
// V8's streaming compiler.
const stream = res.body;
const resourceBacking = getReadableStreamResourceBacking(stream);View on GitHub (pinned to a961cdec3b)