The Problem
WebAssembly.instantiateStreaming is the recommended way to load and compile WebAssembly modules. However, it requires the server to serve .wasm files with the correct application/wasm MIME type. If the MIME type is wrong, the browser rejects the compilation.
Symptoms
- "WebAssembly.instantiateStreaming failed: incorrect response MIME type"
- WASM module does not load
- Works with
WebAssembly.instantiatebut notinstantiateStreaming - Error appears in Chrome and Firefox but may differ per browser
Real Error Message
TypeError: WebAssembly.instantiateStreaming(): Response has unsupported
MIME type 'application/octet-stream' or 'text/html' instead of
'application/wasm'.Common Cause: Server Not Configured for .wasm
// This fails if server returns wrong MIME type
WebAssembly.instantiateStreaming(fetch('/module.wasm'), importObject)
.then(results => {
results.instance.exports.main();
});How to Fix It
Fix 1: Configure Server MIME Type
# nginx.conf
types {
application/wasm wasm;
}# .htaccess
AddType application/wasm .wasm// Express.js
app.use(express.static('public', {
setHeaders: (res, path) => {
if (path.endsWith('.wasm')) {
res.setHeader('Content-Type', 'application/wasm');
}
}
}));Fix 2: Verify MIME Type
```bash curl -I https://example.com/module.wasm
# Should return: # Content-Type: application/wasm ```
Fix 3: Fallback to ArrayBuffer
async function loadWasm(url, importObject) {
try {
// Try streaming first
const response = await fetch(url);
if (response.headers.get('content-type') === 'application/wasm') {
return WebAssembly.instantiateStreaming(response, importObject);
}
// Fallback to ArrayBuffer
const bytes = await response.arrayBuffer();
return WebAssembly.instantiate(bytes, importObject);
} catch (err) {
// If streaming fails for any reason, fall back
const response = await fetch(url);
const bytes = await response.arrayBuffer();
return WebAssembly.instantiate(bytes, importObject);
}
}Fix 4: Webpack Configuration for WASM
// webpack.config.js
module.exports = {
experiments: {
asyncWebAssembly: true
},
module: {
rules: [
{
test: /\.wasm$/,
type: 'webassembly/async'
}
]
}
};Fix 5: ETag and Caching for WASM
location ~* \.wasm$ {
add_header Content-Type application/wasm;
add_header Cache-Control "public, max-age=31536000, immutable";
# WASM files should be content-hashed, so immutable caching is safe
}