{"record":{"id":"5a98b6186140799a","repo":"dotnet/runtime","slug":"failed-to-load-resource-asset-name-from-as","errorCode":null,"errorMessage":"Failed to load resource '${asset.name}' from '${asset.resolvedUrl}': ${message}","messagePattern":"Failed to load resource '(.+?)' from '(.+?)': (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/Common/JavaScript/loader/assets.ts","lineNumber":356,"sourceCode":"        }\n        assetInternal.behavior = \"symbols\";\n        assetInternal.isOptional = assetInternal.isOptional || loaderConfig.ignorePdbLoadErrors;\n        tableText = await fetchText(assetInternal);\n    } finally {\n        onDownloadedAsset(assetInternal);\n    }\n    dotnetDiagnosticsExports.installNativeSymbols(tableText || \"\");\n}\n\nasync function fetchBytes(asset: AssetEntryInternal): Promise<Uint8Array | null> {\n    dotnetAssert.check(asset && asset.resolvedUrl, \"Bad asset.resolvedUrl\");\n    let response: Response;\n    try {\n        response = await loadResource(asset);\n    } catch (err: any) {\n        // Strip .silent flag from download errors so they are properly reported via exit listeners\n        const message = err instanceof Error ? err.message : String(err);\n        throw new Error(`Failed to load resource '${asset.name}' from '${asset.resolvedUrl}': ${message}`, { cause: err });\n    }\n    if (!response.ok) {\n        if (asset.isOptional) {\n            dotnetLogger.warn(`Optional resource '${asset.name}' failed to load from '${asset.resolvedUrl}'. HTTP status: ${response.status} ${response.statusText}`);\n            return null;\n        }\n        throw new Error(`Failed to load resource '${asset.name}' from '${asset.resolvedUrl}'. HTTP status: ${response.status} ${response.statusText}`);\n    }\n    const buffer = await (asset.buffer || response.arrayBuffer());\n    return new Uint8Array(buffer);\n}\n\nasync function fetchText(asset: AssetEntryInternal): Promise<string | null> {\n    dotnetAssert.check(asset && asset.resolvedUrl, \"Bad asset.resolvedUrl\");\n    let response: Response;\n    try {\n        response = await loadResource(asset);\n    } catch (err: any) {","sourceCodeStart":338,"sourceCodeEnd":374,"githubUrl":"https://github.com/dotnet/runtime/blob/60108ba66eb7d1d12f595480091b4ad80a24b172/src/native/libs/Common/JavaScript/loader/assets.ts#L338-L374","documentation":"Wrapped re-throw inside fetchBytes(): loadResource() rejected (network throw, abort, CORS, or an exception thrown by a custom loadBootResourceCallback). The wrapper strips the original .silent flag so the error propagates through exit listeners. Original cause is attached via { cause: err }. Asset bytes could not be obtained at all — no HTTP response was successfully produced.","triggerScenarios":"Network offline or DNS failure during assembly/PDB/ICU/VFS download. CORS preflight rejection blocking the fetch. A user-supplied loadBootResourceCallback that throws or returns a promise that rejects. TLS/cert error on the asset URL. Service Worker returning a rejecting Response promise.","commonSituations":"Running the WASM app from a different origin than the assets without CORS headers. Corporate proxy intercepting requests. Misconfigured CDN returning an opaque response. Custom loadBootResourceCallback returning fetch to a private endpoint that 401s and throws. file:// URLs in Node without the fs polyfill resolved. Asset hash mismatch triggers SRI failure (browser throws).","solutions":["Open DevTools Network tab and inspect the failing request's status/type; the original cause is in err.cause.","If CORS, add Access-Control-Allow-Origin for the WASM app origin on the asset server, or host assets same-origin.","If a custom loadBootResourceCallback throws, guard its body and return a valid Response or string URL.","If SRI hash mismatch, rebuild so the boot manifest hash matches the published asset bytes.","If offline/Node, ensure polyfills.ts nodeFs is initialized before fetch, or pass a globalThis.fetch."],"exampleFix":"// before: custom loader throws on auth failure\noptions.loadBootResource = (type, name, url) => fetch(url); // rejects 401\n\n// after: return a Response, handle auth\noptions.loadBootResource = (type, name, url, integrity, behavior) =>\n  fetch(url, { credentials: 'include' });","handlingStrategy":"try-catch","validationCode":"// Pre-flight the URL is reachable and CORS permits the origin\nasync function canFetchAsset(url: string): Promise<boolean> {\n  try {\n    const r = await fetch(url, { method: 'HEAD', mode: 'cors' });\n    return r.ok || r.status === 405; // 405 = HEAD not allowed but resource exists\n  } catch { return false; }\n}","typeGuard":"function isResponseLike(v: unknown): v is Response {\n  return !!v && typeof v === 'object' && typeof (v as any).arrayBuffer === 'function' && typeof (v as any).ok === 'boolean';\n}","tryCatchPattern":"try {\n  await dotnet.create();\n} catch (e) {\n  const cause = (e as Error)?.cause ?? e;\n  if (/Failed to load resource/.test((e as Error).message)) {\n    reportToUser('Asset download failed', { url: extractUrl(e), cause });\n  }\n  throw e;\n}","preventionTips":["Serve assets same-origin or configure CORS headers explicitly for the app origin.","Smoke-test asset URLs from the deployment environment in CI before release.","Wrap any custom loadBootResourceCallback in try/catch and return a controlled Response on error.","Log err.cause — the wrapped error carries the real network exception."],"tags":["network","fetch","cors","loader"],"backgroundTag":null,"analyzedSha":"60108ba66eb7d1d12f595480091b4ad80a24b172","analyzedAt":"2026-08-10T18:54:11.478Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}