net::ERR_INSUFFICIENT_RESOURCES (too many concurrent requests)
Chrome's network stack runs out of internal resource handles when a page fires too many simultaneous requests, so assets silently fail.
What you see
DevTools Console: GET https://example.com/img/4821.jpg net::ERR_INSUFFICIENT_RESOURCES Uncaught (in promise) TypeError: Failed to fetch
What’s actually happening
Some images never paint, some fetches reject, and which ones fail changes on every reload — it's nondeterministic. This is the browser, not the server: nothing hits your backend logs because Chrome refuses to open the socket in the first place. You'll see it most on pages that loop over a big array kicking off fetch() calls with no concurrency limit, or galleries rendering thousands of <img> tags at once. Firefox and Safari handle the same page differently, so it can look browser-specific.
Common causes
- JavaScript firing hundreds-to-thousands of fetch()/XHR calls in a tight loop or an unbounded Promise.all([...]) with no batching.
- A page rendering thousands of <img> or <iframe> elements with no loading="lazy", so the browser tries to queue them all immediately.
- A retry loop with no backoff hammering an endpoint and piling up in-flight requests faster than they resolve.
- Large request bodies or many simultaneous uploads exhausting memory/handle limits in the renderer.
- A service worker or polling interval re-issuing requests before previous ones complete, compounding the queue.
How to fix it
- Cap concurrencyNever fire an unbounded Promise.all over a big list. Run a worker-pool that keeps N in flight (5–10 is a safe start) and feeds the next request as each resolves. Libraries like p-limit do this in a few lines.
- Lazy-load offscreen assetsAdd loading="lazy" to images/iframes, or use an IntersectionObserver so requests fire only as elements approach the viewport instead of all at once.
- Paginate or virtualize long listsRender a window of rows (react-window / virtual scrolling) so the DOM never holds thousands of resource-loading nodes simultaneously.
- Add backoff to retriesReplace fixed-interval retries with exponential backoff and a max-attempts ceiling so a failing endpoint can't snowball into thousands of queued requests.
- Reproduce with throttlingIn DevTools Network, set a custom throttle to a low concurrent-connection profile to surface the failure reliably, then confirm your batching fix holds under it.
Stop it recurring
Treat outbound requests as a bounded resource: queue them through a concurrency limiter and lazy-load anything below the fold.