dotnet / dotnet/aspnetcore

MapStaticAssets silently fails with 500 for assets when running dotnet run without Development environment

Open
#65,468 3 comments 0 reactions 0 assignees View on GitHub
area-blazor
Dominant language
C#
Stars
38.4k
Forks
10.9k
Avg merge
2d 10h
Merged PRs (30d)
281

Description

### Is there an existing issue for this?

- [x] I have searched the existing issues

### Describe the bug

When running a Blazor Server app via dotnet run without ASPNETCORE_ENVIRONMENT=Development (e.g., no launchSettings.json), all static assets from NuGet packages (_content/*) and framework assets (_framework/*) return HTTP 500 with FileNotFoundException. Project-local assets in wwwroot/ work fine.

There is no documentation indicating that dotnet run requires the Development environment for NuGet or framework static assets to be served.

### Expected Behavior

When using dotnet run even if the environment is set to production MapStaticAssets should work. At the very least this should produce a proper warning and be a documented limitation.

### Steps To Reproduce

1. dotnet new blazor -n ReproApp
2. cd ReproApp
3. DOTNET_ENVIRONMENT=Production dotnet run
4. Open localhost:5xxx you should see the exceptions

Alternatively:

3. rm Properties/launchSettings.json
4. dotnet run
5. Open localhost:5000 you should see the exceptions.

### Exceptions (if any)

[11:56:05 ERR] Connection id "0HNJFKLSO1PV3", Request id "0HNJFKLSO1PV3:00000004": An unhandled exception was thrown by the application.
System.IO.FileNotFoundException: Could not find file '/PATH_TO_PROJECT/wwwroot/_content/MudBlazor/MudBlazor.min.js'.
File name: '/home/felix/projects/apps/helios-batch-download-support/tools/Helios.DocumentAnalyzer/wwwroot/_content/MudBlazor/MudBlazor.min.js'
at System.IO.FileInfo.get_Length()
at Microsoft.AspNetCore.Builder.StaticAssetDevelopmentRuntimeHandler.<>c__DisplayClass3_0.<b__0>d.MoveNext()
--- End of stack trace from previous location ---
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)

### .NET Version

10.0.101

### Anything else?

# Root Cause
WebHost.ConfigureWebDefaults gates StaticWebAssetsLoader.UseStaticWebAssets() behind a hard IsDevelopment() check. This loader reads staticwebassets.runtime.json and configures WebRootFileProvider as a CompositeFileProvider that maps virtual paths (e.g., _content/MudBlazor/...) to their physical locations in the NuGet cache.

Without it, WebRootFileProvider is a plain PhysicalFileProvider pointing at wwwroot/, and MapStaticAssets() endpoints try to resolve _content/MudBlazor/MudBlazor.min.css from wwwroot/_content/MudBlazor/MudBlazor.min.css — which doesn't exist (only dotnet publish copies those files there).

MapStaticAssets() itself works in all environments, but it depends on WebRootFileProvider being correctly configured — which only happens in Development.

Contributor guide

Open the contributing guide

Research direction

Start with WebHost.ConfigureWebDefaults and the StaticWebAssetsLoader.UseStaticWebAssets() environment check, then trace how MapStaticAssets resolves _content and _framework paths. Reproduce with a Blazor app using DOTNET_ENVIRONMENT=Production or without launchSettings.json. Done means production dotnet run serves package and framework assets correctly, or emits a documented warning instead of a 500.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.