{"record":{"id":"fa704bd53dabe5db","repo":"denoland/deno","slug":"invalid-webassembly-content-type","errorCode":null,"errorMessage":"Invalid WebAssembly content type","messagePattern":"Invalid WebAssembly content type","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"ext/fetch/26_fetch.js","lineNumber":1027,"sourceCode":"  try {\n    const res = webidl.converters[\"Response\"](\n      source,\n      \"Failed to execute 'WebAssembly.compileStreaming'\",\n      \"Argument 1\",\n    );\n\n    // 2.3.\n    // The spec is ambiguous here, see\n    // https://github.com/WebAssembly/spec/issues/1138. The WPT tests expect\n    // the raw value of the Content-Type attribute lowercased. We ignore this\n    // for file:// because file fetches don't have a Content-Type.\n    if (!StringPrototypeStartsWith(res.url, \"file://\")) {\n      const contentType = res.headers.get(\"Content-Type\");\n      if (\n        typeof contentType !== \"string\" ||\n        StringPrototypeToLowerCase(contentType) !== \"application/wasm\"\n      ) {\n        throw new TypeError(\"Invalid WebAssembly content type\");\n      }\n    }\n\n    // 2.5.\n    if (!res.ok) {\n      throw new TypeError(\n        `Failed to receive WebAssembly content: HTTP status code ${res.status}`,\n      );\n    }\n\n    // Pass the resolved URL to v8.\n    op_wasm_streaming_set_url(rid, res.url);\n\n    if (res.body !== null) {\n      // 2.6.\n      // Rather than consuming the body as an ArrayBuffer, this feeds each chunk\n      // to the streaming compiler as soon as it's available. Instead of reading\n      // the body chunk-by-chunk in JS and calling `op_wasm_streaming_feed` once","sourceCodeStart":1009,"sourceCodeEnd":1045,"githubUrl":"https://github.com/denoland/deno/blob/89f33cbef296a2b287f323d42de54c871fa69c77/ext/fetch/26_fetch.js#L1009-L1045","documentation":"WebAssembly.compileStreaming/instantiateStreaming in Deno validate the response Content-Type: it must equal 'application/wasm' after lowercasing, otherwise the compiler would be fed bytes of unknown type. The check is skipped for file:// URLs because file fetches carry no Content-Type. Note the comparison is exact, so parameters such as 'application/wasm; charset=utf-8' are rejected too.","triggerScenarios":"A server responding with Content-Type: text/plain, application/octet-stream, no Content-Type header, or application/wasm with appended parameters (charset) when the wasm module is fetched for instantiateStreaming; happens for http(s) URLs but not file://.","commonSituations":"Static file servers that guess MIME types and mark .wasm as application/octet-stream; dev servers without a wasm MIME mapping; CDNs/frameworks that append charset to every text-ish response; proxy layers stripping headers.","solutions":["Serve the module with exactly 'Content-Type: application/wasm' and no parameters","Fall back to non-streaming compilation: WebAssembly.instantiate(await res.arrayBuffer(), imports)","If you cannot change headers, fetch the bytes first, verify manually, then compile from the buffer"],"exampleFix":"// before\nconst { instance } = await WebAssembly.instantiateStreaming(fetch(\"/lib.wasm\")); // Invalid WebAssembly content type\n\n// after (option 1: fix server header to application/wasm)\n// after (option 2: compile from buffer)\nconst res = await fetch(\"/lib.wasm\");\nif (!res.ok) throw new Error(`HTTP ${res.status}`);\nconst { instance } = await WebAssembly.instantiate(await res.arrayBuffer());","handlingStrategy":"fallback","validationCode":"function isWasmResponseType(res) {\n  const ct = res.headers.get(\"content-type\");\n  return typeof ct === \"string\" && ct.toLowerCase().split(\";\")[0].trim() === \"application/wasm\";\n}","typeGuard":"function canStreamCompile(res: Response): boolean {\n  const ct = res.headers.get(\"content-type\");\n  return res.ok && ct !== null && ct.toLowerCase().startsWith(\"application/wasm\");\n}","tryCatchPattern":"async function instantiateAnyhow(url, imports) {\n  const res = await fetch(url);\n  if (!res.ok) throw new Error(`HTTP ${res.status}`);\n  try {\n    return await WebAssembly.instantiateStreaming(Promise.resolve(res), imports);\n  } catch (err) {\n    if (err instanceof TypeError && err.message === \"Invalid WebAssembly content type\") {\n      return await WebAssembly.instantiate(await res.arrayBuffer(), imports); // non-streaming fallback\n    }\n    throw err;\n  }\n}","preventionTips":["Serve .wasm with exactly 'application/wasm' (no charset parameters) and verify with curl -I","Validate the content-type header yourself before choosing the streaming API","Keep a buffer-based compile path for servers you do not control","Remember file:// URLs skip the check but servers do not"],"tags":["webassembly","content-type","mime","streaming-compilation"],"backgroundTag":null,"analyzedSha":"89f33cbef296a2b287f323d42de54c871fa69c77","analyzedAt":"2026-08-16T07:54:21.310Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}