ERR_HTTP2_SERVER_REFUSED_STREAM: Chrome Fix
ERR_HTTP2_SERVER_REFUSED_STREAM: the server refused the request unprocessed. Check load balancer, HTTP/2 limits, and cookies. Free instant check, no sign-up.
Check your domain for this issue now
Free, no sign-up. Runs the exact check this guide describes and shows what to fix.
Problem
Chrome fails to load the page or some of its resources with ERR_HTTP2_SERVER_REFUSED_STREAM, often intermittently — a reload fixes it, or it hits a different set of files each time. This one has a precise meaning that most “clear your cache” advice completely misses: the server didn’t crash and didn’t time out. It deliberately refused to process the request, and it’s still refusing after Chrome quietly retried.
Symptoms
- Chrome (or Edge) shows
net::ERR_HTTP2_SERVER_REFUSED_STREAM, frequently for individual assets (JS, CSS, images) rather than the whole page. - It’s intermittent and often affects a changing subset of requests on reload — a strong sign of a connection-level or capacity issue, not a broken URL.
- It can appear across multiple sites that sit behind the same CDN or IP.
- It sometimes clears after clearing cookies for the site, or in Incognito with extensions off.
What This Error Actually Means
HTTP/2 carries many requests as independent streams over one long-lived connection. A server is allowed to refuse a stream, and it has two clean ways to do it. It can send an RST_STREAM frame carrying the error code REFUSED_STREAM (0x7), or it can send a GOAWAY frame with error code NO_ERROR and a Last-Stream-ID below the stream ID of your request — telling the client “I’m winding this connection down and won’t process anything past here.” Chrome recognizes both patterns and, when a request is refused this way, raises ERR_HTTP2_SERVER_REFUSED_STREAM.
The critical detail is that a refusal is a promise the request was not processed. RFC 9113 §8.1.1 is explicit: a request on a stream reset with REFUSED_STREAM “can be safely retried.” That’s why this rarely surfaces to users on the first occurrence — Chrome takes the hint and retries the request on a fresh connection automatically. So when you actually see the error, it means the retry got refused too. The refusal isn’t a single graceful GOAWAY during a deploy; it’s a condition that keeps happening.
That reframes the whole diagnosis. You’re not looking for a broken page. You’re looking for why a server, load balancer, or proxy is repeatedly telling Chrome “not now” — capacity, a graceful-shutdown loop, or an outright HTTP/2 bug.
Top 3 Causes
- A load balancer or reverse proxy with a buggy HTTP/2 implementation - This is the most common real-world cause, and it’s frustrating because the origin is fine. HTTP/2 stacks in front-end appliances have shipped bugs that refuse streams under specific conditions — one well-documented case was F5 BIG-IP’s HTTP/2 profile refusing streams for Chrome clients, and similar reports exist against HAProxy and nginx-based proxies. Requests never reach your app; the edge kills them. The fix is on the proxy: patch it, or (as a stopgap) reconsider its HTTP/2 profile.
- The connection hit a concurrency or graceful-shutdown boundary - A server has a
SETTINGS_MAX_CONCURRENT_STREAMSlimit; a well-behaved client queues new streams when it’s reached, but a fragile server or proxy can refuse them instead. Separately, during a deploy, scale-down, or keepalive expiry, a server sends GOAWAY to drain a connection — normal, and Chrome should retry elsewhere. It turns into a visible error when a load balancer keeps handing the browser back onto draining connections, so every retry lands somewhere that’s also shutting down. - Oversized request headers, often bloated cookies - A large accumulation of cookies (or a giant JWT) inflates the request header block. Some HTTP/2 implementations mishandle
SETTINGS_MAX_HEADER_LIST_SIZEand refuse the stream rather than returning a clean 431. This is why clearing the site’s cookies sometimes works — and why it comes back if the app just rebuilds them.
Diagnose with DechoNet
- HTTP Check fetches the site from outside your browser and network. If it returns a clean response while your browser keeps failing, the problem is on your side — a coalesced/reused connection, an extension, or bloated cookies — not the origin.
- SSL Check confirms TLS and ALPN are healthy, since HTTP/2 is negotiated during the TLS handshake; a clean result rules out the layer beneath the stream error.
- Port Check verifies port 443 is reachable, separating a genuine connectivity problem from an HTTP/2-level refusal.
Resolution Checklist
- Separate client from server first. Run an external HTTP check, or load the site in Incognito with extensions disabled. Clean externally but broken in your browser → suspect cookies, an extension, or connection reuse on your side.
- Clear cookies for the affected site (or test in a fresh profile). If it fixes it, your request headers were oversized — trim what the app stores in cookies, and make sure the server returns a proper 431 instead of refusing streams.
- If it fails for many users or across sites behind one edge, treat it as a proxy/LB HTTP/2 bug: update the load balancer, CDN, or reverse-proxy software, and check vendor notes for HTTP/2 stream-refusal fixes.
- If it clusters around deploys or scaling events, look at graceful shutdown: ensure GOAWAY draining and load-balancer connection handling let clients move off draining connections cleanly instead of being routed back onto them.
- Re-run the HTTP check after the change to confirm requests are being processed, not refused.
When to Escalate
- If an external HTTP check shows a healthy origin but the error only appears through a CDN or load balancer, escalate to that vendor with the detail that it’s sending RST_STREAM REFUSED_STREAM (or a GOAWAY drain) — that’s a front-end HTTP/2 problem, not your application.
- If it tracks with traffic volume, escalate as capacity or a
MAX_CONCURRENT_STREAMShandling issue: the tier in front is refusing streams under load rather than queueing them. - If it’s tied to release windows, hand it to whoever owns deploys and load-balancer config — connections are being drained faster than clients can migrate off them.
Related Tools
Related Guides
Share this guide