dotnet/runtime · error · Error

Failed to load resource '${asset.name}' from '${asset.resolv

Error message

Failed to load resource '${asset.name}' from '${asset.resolvedUrl}'. HTTP status: ${response.status} ${response.statusText}

What it means

fetchBytes: loadResource returned a Response with response.ok === false and the asset is not marked isOptional. The HTTP status and statusText are surfaced. This is the non-optional HTTP-error path — optional assets only warn.

Source

Thrown at src/native/libs/Common/JavaScript/loader/assets.ts:363

    dotnetDiagnosticsExports.installNativeSymbols(tableText || "");
}

async function fetchBytes(asset: AssetEntryInternal): Promise<Uint8Array | null> {
    dotnetAssert.check(asset && asset.resolvedUrl, "Bad asset.resolvedUrl");
    let response: Response;
    try {
        response = await loadResource(asset);
    } catch (err: any) {
        // Strip .silent flag from download errors so they are properly reported via exit listeners
        const message = err instanceof Error ? err.message : String(err);
        throw new Error(`Failed to load resource '${asset.name}' from '${asset.resolvedUrl}': ${message}`, { cause: err });
    }
    if (!response.ok) {
        if (asset.isOptional) {
            dotnetLogger.warn(`Optional resource '${asset.name}' failed to load from '${asset.resolvedUrl}'. HTTP status: ${response.status} ${response.statusText}`);
            return null;
        }
        throw new Error(`Failed to load resource '${asset.name}' from '${asset.resolvedUrl}'. HTTP status: ${response.status} ${response.statusText}`);
    }
    const buffer = await (asset.buffer || response.arrayBuffer());
    return new Uint8Array(buffer);
}

async function fetchText(asset: AssetEntryInternal): Promise<string | null> {
    dotnetAssert.check(asset && asset.resolvedUrl, "Bad asset.resolvedUrl");
    let response: Response;
    try {
        response = await loadResource(asset);
    } catch (err: any) {
        // Strip .silent flag from download errors so they are properly reported via exit listeners
        const message = err instanceof Error ? err.message : String(err);
        throw new Error(`Failed to load resource '${asset.name}' from '${asset.resolvedUrl}': ${message}`, { cause: err });
    }
    if (!response.ok) {
        if (asset.isOptional) {
            dotnetLogger.warn(`Optional resource '${asset.name}' failed to load from '${asset.resolvedUrl}'. HTTP status: ${response.status} ${response.statusText}`);

View on GitHub (pinned to 290d5ab72c)

Solutions

  1. GET the resolvedUrl directly and read the exact HTTP status to diagnose (404 → missing file, 403 → auth).
  2. Ensure the published wwwroot/_framework contains every assembly/pdb/icu listed in the boot config.
  3. Fix the applicationBase / virtualWorkingDirectory if URLs resolve to the wrong path.
  4. For auth-protected deployments, allow anonymous GET on static framework files or use a loadBootResource callback that adds credentials.

Example fix

// before: framework files behind auth middleware
app.UseAuthentication();
app.UseAuthorization();
app.UseStaticFiles(); // 401 for /_framework/*.dll

// after: allow anonymous on framework assets
app.UseStaticFiles(new StaticFileOptions {
  FileProvider = new PhysicalFileProvider(Path.Combine(env.WebRootPath, "_framework")),
  RequestPath = "/_framework",
  OnPrepareResponse = ctx => ctx.Context.Response.Headers.Append("Cache-Control", "public")
});
Defensive patterns

Strategy: validation

Validate before calling

async function assetReachable(url: string): Promise<boolean> {
  const r = await fetch(url, { method: 'HEAD' });
  return r.ok;
}
if (!await assetReachable(asset.resolvedUrl)) {
  throw new Error(`Server returned non-200 for ${asset.resolvedUrl} — check deployment`);
}

Try / catch

try { await runtime.fetchAsset(asset); }
catch (err) {
  const m = err.message.match(/HTTP status: (\d+)/);
  if (m) {
    const status = +m[1];
    if (status === 404) reportMissingFile(asset);
    else if (status === 401 || status === 403) reportAuthIssue(asset);
  }
  throw err;
}

Prevention

When it happens

Trigger: Server returned 4xx/5xx for a required binary asset (assembly, pdb, icu, vfs). E.g. 404 because the file is missing from the deploy, 401/403 due to auth, 500 from a misconfigured server.

Common situations: File missing from publish output (404); auth-protected static files (401/403); reverse proxy or CDN misroute (502/504); wrong applicationBase path resolving the URL; file deleted from the server after boot config was generated.

Related errors


AI-assisted analysis of dotnet/runtime@290d5ab72c (2026-08-06). Data as JSON: /api/errors/2f586be136b15e4c. Report an issue: GitHub.