Introduction

Blazor WebAssembly downloads the entire .NET runtime and application assemblies as .dll and .wasm files on first load. When served from a CDN or static hosting, misconfigured MIME types, incorrect compression headers, CDN caching of stale blazor.boot.json, or subresource integrity (SRI) mismatches cause the application to fail during startup with download timeout or corrupted file errors. The boot process is sensitive to file consistency — every file referenced in blazor.boot.json must be available with the correct content type and hash.

Symptoms

  • "WASM download timeout" error in browser console
  • "Failed to load resource: net::ERR_CONTENT_LENGTH_MISMATCH"
  • Blazor stuck on loading screen with progress at partial percentage
  • "Corrupted .dll" or "Invalid Blazor boot resource" errors
  • Application loads in development but fails on production CDN
  • Intermittent failures that clear after hard refresh

Error output: `` WASM: Downloading dotnet.wasm... Error: Failed to start platform. Reason: Error: Failed to load resource: the server responded with a status of 404 (Not Found) blazor.webassembly.js:1 WASM: System.IO.IOException: Corrupted .dll file.

Common Causes

  • CDN caching stale blazor.boot.json while new DLLs are deployed
  • MIME type not configured for .dll, .wasm, .dat, .blat files
  • Gzip/Brotli compression not matching what blazor.boot.json expects
  • Subresource integrity hash mismatch after deployment
  • CDN not serving pre-compressed files from wwwroot subdirectories
  • Network timeout for large runtime files on slow connections

Step-by-Step Fix

  1. 1.Configure correct MIME types on CDN or web server:
  2. 2.```xml
  3. 3.<!-- web.config for IIS/Azure Static Web Apps -->
  4. 4.<configuration>
  5. 5.<system.webServer>
  6. 6.<staticContent>
  7. 7.<remove fileExtension=".dll" />
  8. 8.<mimeMap fileExtension=".dll" mimeType="application/octet-stream" />
  9. 9.<remove fileExtension=".wasm" />
  10. 10.<mimeMap fileExtension=".wasm" mimeType="application/wasm" />
  11. 11.<remove fileExtension=".blat" />
  12. 12.<mimeMap fileExtension=".blat" mimeType="application/octet-stream" />
  13. 13.<remove fileExtension=".dat" />
  14. 14.<mimeMap fileExtension=".dat" mimeType="application/octet-stream" />
  15. 15.<remove fileExtension=".json.gz" />
  16. 16.<mimeMap fileExtension=".json.gz" mimeType="application/octet-stream" />
  17. 17.<remove fileExtension=".wasm.gz" />
  18. 18.<mimeMap fileExtension=".wasm.gz" mimeType="application/wasm" />
  19. 19.<remove fileExtension=".dll.gz" />
  20. 20.<mimeMap fileExtension=".dll.gz" mimeType="application/octet-stream" />
  21. 21.<remove fileExtension=".json.br" />
  22. 22.<mimeMap fileExtension=".json.br" mimeType="application/octet-stream" />
  23. 23.<remove fileExtension=".wasm.br" />
  24. 24.<mimeMap fileExtension=".wasm.br" mimeType="application/wasm" />
  25. 25.</staticContent>
  26. 26.</system.webServer>
  27. 27.</configuration>
  28. 28.`
  29. 29.Configure CDN cache headers to prevent stale boot files:
  30. 30.```xml
  31. 31.<!-- web.config - cache control for Blazor files -->
  32. 32.<configuration>
  33. 33.<system.webServer>
  34. 34.<staticContent>
  35. 35.<!-- blazor.boot.json must NEVER be cached long-term -->
  36. 36.</staticContent>
  37. 37.<rewrite>
  38. 38.<outboundRules>
  39. 39.<rule name="No cache for boot files" preCondition="IsBootFile">
  40. 40.<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
  41. 41.<action type="Rewrite" value="no-cache, no-store, must-revalidate" />
  42. 42.</rule>
  43. 43.<rule name="Long cache for hashed DLLs" preCondition="IsDllOrWasm">
  44. 44.<match serverVariable="RESPONSE_Cache-Control" pattern=".*" />
  45. 45.<action type="Rewrite" value="public, max-age=31536000, immutable" />
  46. 46.</rule>
  47. 47.<preConditions>
  48. 48.<preCondition name="IsBootFile">
  49. 49.<add input="{REQUEST_URI}" pattern="blazor\.boot\.json" />
  50. 50.</preCondition>
  51. 51.<preCondition name="IsDllOrWasm">
  52. 52.<add input="{REQUEST_URI}" pattern="\.(dll|wasm|dat)$" />
  53. 53.</preCondition>
  54. 54.</preConditions>
  55. 55.</outboundRules>
  56. 56.</rewrite>
  57. 57.</system.webServer>
  58. 58.</configuration>
  59. 59.`
  60. 60.Disable subresource integrity if CDN modifies file content:
  61. 61.```xml
  62. 62.<!-- In the Blazor WebAssembly .csproj file -->
  63. 63.<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
  64. 64.<PropertyGroup>
  65. 65.<TargetFramework>net9.0</TargetFramework>
  66. 66.<!-- Disable SRI when CDN rewrites files (e.g., adds analytics scripts) -->
  67. 67.<BlazorCacheBootResources>false</BlazorCacheBootResources>
  68. 68.</PropertyGroup>
  69. 69.</Project>

<!-- Or disable SRI in index.html --> <script src="_framework/blazor.webassembly.js" autostart="false"></script> <script> Blazor.start({ loadBootResource: function (type, name, defaultUri, integrity) { // Return empty integrity string to skip SRI check return fetch(defaultUri, { integrity: '', // Skip SRI verification cache: 'no-cache' }); } }); </script> ```

  1. 1.Configure Blazor to handle compressed resources correctly:
  2. 2.```csharp
  3. 3.// Program.cs - for Blazor WebAssembly
  4. 4.var builder = WebAssemblyHostBuilder.CreateDefault(args);

// Custom boot resource loading with retry logic builder.RootComponents.Add<App>("#app");

// In wwwroot/index.html, configure compression headers: // The server must serve Content-Encoding: gzip or br for .gz/.br files // AND set Vary: Accept-Encoding so CDN caches both compressed and uncompressed

// nginx configuration example: // location ~ \.(wasm|dll|dat)$ { // gzip_static on; // brotli_static on; // add_header Content-Encoding $content_encoding; // add_header Vary Accept-Encoding; // } ```

  1. 1.Add loading timeout and user feedback:
  2. 2.```html
  3. 3.<!-- wwwroot/index.html -->
  4. 4.<div id="app">
  5. 5.<div id="loading">
  6. 6.<div class="progress-bar">
  7. 7.<div id="progress"></div>
  8. 8.</div>
  9. 9.<p id="loading-status">Loading Blazor application...</p>
  10. 10.<p id="loading-error" style="display:none; color:red;">
  11. 11.Application failed to load. Please
  12. 12.<a href="javascript:location.reload()">refresh the page</a>.
  13. 13.If the problem persists, check your network connection.
  14. 14.</p>
  15. 15.</div>
  16. 16.</div>

<script> // Timeout after 60 seconds const timeout = setTimeout(() => { document.getElementById('loading-status').style.display = 'none'; document.getElementById('loading-error').style.display = 'block'; }, 60000);

Blazor.start().then(() => { clearTimeout(timeout); }).catch((err) => { clearTimeout(timeout); document.getElementById('loading-status').style.display = 'none'; document.getElementById('loading-error').style.display = 'block'; console.error('Blazor startup failed:', err); }); </script> ```

Prevention

  • Deploy blazor.boot.json LAST, after all DLLs and WASM files are uploaded
  • Purge CDN cache after every deployment
  • Use cache-busting URLs or versioned CDN paths for new releases
  • Configure MIME types for all Blazor resource extensions
  • Monitor Blazor startup times with application insights
  • Test on slow network connections using browser dev tools throttling
  • Use blazor.boot.json hash verification to detect deployment inconsistencies
  • Consider lazy loading assemblies with @attribute [System.Runtime.CompilerServices.MethodImpl]