{"record":{"id":"2f0d1e122c8a2e84","repo":"dotnet/runtime","slug":"failed-to-load-resource-asset-name-from-as-2f0d1e","errorCode":null,"errorMessage":"Failed to load resource '${asset.name}' from '${asset.resolvedUrl}' after multiple attempts. Last HTTP status: ${response.status} ${response.statusText}","messagePattern":"Failed to load resource '(.+?)' from '(.+?)' after multiple attempts\\. Last HTTP status: (.+?) (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/native/libs/Common/JavaScript/loader/assets.ts","lineNumber":426,"sourceCode":"    }\n    // second attempt only after all first attempts are queued\n    await allDownloadsQueuedPCS.promise;\n    if (response.status === 429) {\n        // Too Many Requests\n        await delay(100);\n    }\n    dotnetLogger.debug(`Retrying download '${asset.name}'`);\n    response = await loadResourceAttempt();\n    if (response.ok || noRetryStatusCodes.has(response.status)) {\n        return response;\n    }\n    await delay(100); // wait 100ms before the last retry\n    dotnetLogger.debug(`Retrying download (2) '${asset.name}' after delay`);\n    response = await loadResourceAttempt();\n    if (response.ok) {\n        return response;\n    }\n    throw new Error(`Failed to load resource '${asset.name}' from '${asset.resolvedUrl}' after multiple attempts. Last HTTP status: ${response.status} ${response.statusText}`);\n\n    async function loadResourceAttempt(): Promise<Response> {\n        let response: Response;\n        try {\n            response = await loadResourceThrottle(asset);\n            if (!response) {\n                response = responseLike(asset.resolvedUrl!, null, {\n                    status: 404,\n                    statusText: \"No response\",\n                });\n            }\n        } catch (err: any) {\n            response = responseLike(asset.resolvedUrl!, null, {\n                status: 500,\n                statusText: err.message || \"Exception during fetch\",\n            });\n        }\n        return response;","sourceCodeStart":408,"sourceCodeEnd":444,"githubUrl":"https://github.com/dotnet/runtime/blob/290d5ab72cc1102813fbc0406fb186ceadabc340/src/native/libs/Common/JavaScript/loader/assets.ts#L408-L444","documentation":"loadResourceRetry tries an asset up to three times (initial + 2 retries, with a 100ms backoff and a 429-specific delay). If the final response is still not ok and its status is not in noRetryStatusCodes (400,401,403,404,405,406,409,410,411,413,414,415,422,426,501,505), it throws this final-after-retries error.","triggerScenarios":"A retriable HTTP status (500, 502, 503, 504, 429, or transient 200-less failures) persisted across all three attempts. Permanent statuses (4xx listed above) return immediately without this message.","commonSituations":"Server/CDN instability; rate limiting (429) that the 100ms delay did not absorb; backend overload during a cold start; flaky reverse proxy returning 502/504; deployment in progress causing transient 500s.","solutions":["Inspect the Last HTTP status in the message — 502/503/504 indicates upstream server/CDN problems; 429 indicates rate limiting.","For 429, raise server-side rate limits or stagger asset requests (lower maxParallelDownloads in loaderConfig).","For 502/503/504, verify backend health and increase uptime/restart capacity; retry loading the page once the backend recovers.","If you control the server, ensure all framework assets return 200 reliably and consider a CDN with longer cache TTLs."],"exampleFix":"// before\nbuilder.withConfig({ maxParallelDownloads: 64 }); // overwhelms server → 429s\n\n// after\nbuilder.withConfig({ maxParallelDownloads: 4 }); // gentler ramp, avoids 429 retries","handlingStrategy":"retry","validationCode":"// Probe server stability before starting\nconst codes = await Promise.all([1,2,3].map(() => fetch(base).then(r => r.status).catch(() => 0)));\nif (codes.some(c => c >= 500)) console.warn('Backend unstable; expect retry exhaustion');","typeGuard":null,"tryCatchPattern":"try { await loadAll(); }\ncatch (err) {\n  if (/after multiple attempts/.test(err.message)) {\n    // exponential backoff then reload the page / re-run create()\n    await delay(1000); location.reload();\n  } else throw err;\n}","preventionTips":["Keep maxParallelDownloads modest to avoid 429 storms.","Monitor backend 5xx rates; alert before they reach end users.","Use a CDN with aggressive caching to reduce origin load."],"tags":["network","http","retry","transient","rate-limiting"],"analyzedSha":"290d5ab72cc1102813fbc0406fb186ceadabc340","analyzedAt":"2026-08-06T19:57:01.276Z","schemaVersion":2},"datasetVersion":"2026-08-06T23:17:07.152Z"}