Troubleshooting Guide: HTTP/2 Connection Failures and GOAWAY Frames
Quick Fix Summary
TL;DRVerify TLS ALPN negotiation and ensure both client and server send the correct HTTP/2 connection preface.
An HTTP/2 connection fails when the initial 'connection preface' (the string 'PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n') is not correctly exchanged. The server responds with a GOAWAY frame to terminate the connection.
Diagnosis & Causes
Recovery Steps
Step 1: Capture and Analyze the TLS Handshake
Use OpenSSL's s_client to verify the Application-Layer Protocol Negotiation (ALPN) and inspect the raw connection preface.
openssl s_client -alpn h2 -connect example.com:443 -servername example.com
echo -ne "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" | openssl s_client -alpn h2 -connect example.com:443 -ign_eof Step 2: Inspect Server Logs for GOAWAY Frames
Check server application and access logs for HTTP/2-specific error codes. The GOAWAY frame includes a last-stream-id and error code.
grep -i "GOAWAY\|PROTOCOL_ERROR\|HTTP_2" /var/log/nginx/error.log
journalctl -u nginx --since "5 minutes ago" | grep -E "(err|h2)" Step 3: Use a Packet Capture (tcpdump) to See the Preface
Capture the first packets of the connection to see the exact bytes sent by the client and the server's GOAWAY response.
sudo tcpdump -i any -s 0 -A 'host example.com and port 443' -w /tmp/h2_capture.pcap
tcpdump -r /tmp/h2_capture.pcap -X -s 0 | head -50 Step 4: Verify Client Configuration and Libraries
Ensure your HTTP client (curl, browser, application library) is configured for HTTP/2 and is using a compatible version.
curl -v --http2 https://example.com
# For Java/OkHttp: OkHttpClient client = new OkHttpClient.Builder().protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1)).build(); Step 5: Check for Interfering Proxies or Middleware
Temporarily bypass any reverse proxies, WAFs, or API gateways to test a direct connection to the backend server.
# Test direct to backend IP (if accessible)
curl -v --http2 https://<backend-server-ip>:<port> --resolve example.com:443:<backend-server-ip> Step 6: Configure Server for Strict HTTP/2 Compliance
Explicitly set HTTP/2 directives and ensure no modules are interfering. Example for Nginx.
listen 443 ssl http2;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5; Architect's Pro Tip
"The GOAWAY frame's error code (found in logs/pcaps) is key. Code 0x1 (PROTOCOL_ERROR) often points directly to the malformed preface, while 0x7 (ENHANCE_YOUR_CALM) suggests load-related throttling."
Frequently Asked Questions
Can HTTP/1.1 and HTTP/2 connections cause this issue?
Yes. If a client expecting HTTP/2 receives an HTTP/1.1 response (or vice versa) during the preface exchange, it will result in a PROTOCOL_ERROR and GOAWAY. This is often due to missing or incorrect ALPN.
Is this error always caused by the client?
No. While a malformed client preface is common, a misconfigured server, an interfering network device (like a proxy that doesn't fully support HTTP/2), or server-side throttling can also initiate the GOAWAY frame.