redis/redis-py · error · ConnectionError

Bad response from PING health check

Error message

Bad response from PING health check

What it means

Raised as a ConnectionError by _send_ping during a health check when the PING command's response is not 'PONG'. The socket is alive but the server returned an unexpected/garbled reply, indicating protocol corruption or a misbehaving intermediary. Health checks run periodically when health_check_interval is set.

Source

Thrown at redis/connection.py:1321

            self.maintenance_state = MaintenanceState.NONE
            # reset the sets that keep track of received start maint
            # notifications and skipped end maint notifications
            self.reset_received_notifications()

    def mark_for_reconnect(self):
        self._should_reconnect = True

    def should_reconnect(self):
        return self._should_reconnect

    def reset_should_reconnect(self):
        self._should_reconnect = False

    def _send_ping(self):
        """Send PING, expect PONG in return"""
        self.send_command("PING", check_health=False)
        if str_if_bytes(self.read_response()) != "PONG":
            raise ConnectionError("Bad response from PING health check")

    def _ping_failed(self, error, failure_count):
        """Function to call when PING fails"""
        self.disconnect(
            error=error, failure_count=failure_count, health_check_failed=True
        )

    def check_health(self):
        """Check the health of the connection with a PING/PONG"""
        if self.health_check_interval and time.monotonic() > self.next_health_check:
            self.retry.call_with_retry(
                self._send_ping,
                self._ping_failed,
                with_failure_count=True,
            )

    def send_packed_command(self, command, check_health=True):
        """Send an already packed command to the Redis server"""

View on GitHub (pinned to da03cdc7e8)

Solutions

  1. Let the connection be discarded and retried (the client disconnects on this error).
  2. Investigate any proxy/LB between client and server for non-Redis responses.
  3. Reduce connection-pool reuse issues by lowering socket_timeout / health_check_interval.
  4. Check server logs for OOM or protocol-level problems.

Example fix

// before
r = redis.Redis(host=h, health_check_interval=120)
// after
r = redis.Redis(host=h, health_check_interval=30)  # detect bad sockets sooner
Defensive patterns

Strategy: retry

Try / catch

try:
    r.set('k', 'v')
except redis.exceptions.ConnectionError as e:
    if 'PING health check' in str(e):
        # poisoned socket discarded; retry on a fresh connection
        r.set('k', 'v')

Prevention

When it happens

Trigger: The periodic check_health() (gated by health_check_interval) calls _send_ping; if read_response() yields anything other than 'PONG', this fires. Common with a proxy returning an HTML error page, a connection pool handing back a poisoned/corrupted socket, or a RESP parsing desync.

Common situations: A misbehaving proxy/load balancer injecting non-Redis bytes; RESP parser desync after a malformed response; socket reused from a pool in a bad state; server under extreme memory pressure returning OOM-style replies on PING.

Related errors


AI-assisted analysis of redis/redis-py@da03cdc7e8 (2026-08-04). Data as JSON: /data/errors/c338869636befef1.json. Report an issue: GitHub.