# gRPC error: INTERNAL: HTTP/2 ping timeout

- **ID:** `api/grpc-error-internal-http2-ping-timeout`
- **Domain:** api
- **Category:** protocol_error
- **Error Code:** `INTERNAL`
- **Verification:** ai_generated
- **Fix Rate:** 85%

## Root Cause

The gRPC client or server failed to receive a PING acknowledgment within the keepalive timeout period, causing the connection to be closed.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| gRPC Go 1.62 | active | — | — |
| gRPC Python 1.60 | active | — | — |
| Envoy 1.28 | active | — | — |
| gRPC-Web 1.50 | active | — | — |
| Istio 1.20 | active | — | — |

## Workarounds

1. **Set consistent keepalive parameters on both client and server. In gRPC Go, use grpc.WithKeepaliveParams(keepalive.ClientParameters{Time: 10 * time.Second, Timeout: 5 * time.Second, PermitWithoutStream: true}). On the server, set keepalive.EnforcementPolicy{MinTime: 10 * time.Second, PermitWithoutStream: true}.** (90% success)
   ```
   Set consistent keepalive parameters on both client and server. In gRPC Go, use grpc.WithKeepaliveParams(keepalive.ClientParameters{Time: 10 * time.Second, Timeout: 5 * time.Second, PermitWithoutStream: true}). On the server, set keepalive.EnforcementPolicy{MinTime: 10 * time.Second, PermitWithoutStream: true}.
   ```
2. **If using Envoy, add 'http2_protocol_options: { connection_keepalive: { interval: 10s, timeout: 5s } }' to the cluster configuration.** (85% success)
   ```
   If using Envoy, add 'http2_protocol_options: { connection_keepalive: { interval: 10s, timeout: 5s } }' to the cluster configuration.
   ```
3. **Check for network intermediaries (e.g., firewalls, load balancers) that may drop HTTP/2 PING frames. Configure them to allow HTTP/2 keepalive packets.** (80% success)
   ```
   Check for network intermediaries (e.g., firewalls, load balancers) that may drop HTTP/2 PING frames. Configure them to allow HTTP/2 keepalive packets.
   ```

## Dead Ends

- **** — Keepalive is essential for detecting dead connections; disabling it can lead to stale connections. (50% fail)
- **** — The server may have a lower keepalive threshold, causing the server to close the connection first. (70% fail)
- **** — The issue is a configuration mismatch, not a code bug. (90% fail)
