Views: 13

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

  1. 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.
  2. The connection hit a concurrency or graceful-shutdown boundary - A server has a SETTINGS_MAX_CONCURRENT_STREAMS limit; 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.
  3. 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_SIZE and 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_STREAMS handling 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

[Ad] Guide Detail Inline
← Back to All Guides