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.instantiate but not instantiateStreaming
  • Error appears in Chrome and Firefox but may differ per browser

Real Error Message

bash
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

javascript
// 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
# nginx.conf
types {
  application/wasm wasm;
}
apache
# .htaccess
AddType application/wasm .wasm
javascript
// 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

javascript
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

javascript
// webpack.config.js
module.exports = {
  experiments: {
    asyncWebAssembly: true
  },
  module: {
    rules: [
      {
        test: /\.wasm$/,
        type: 'webassembly/async'
      }
    ]
  }
};

Fix 5: ETag and Caching for WASM

nginx
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
}