redis/jedis · critical · JedisConnectionException

Attempting to read from a broken connection.

Error message

Attempting to read from a broken connection.

What it means

readProtocolWithCheckingBroken() refuses to read a reply from a connection previously marked broken, throwing JedisConnectionException with the stored brokenCause. Reading from a broken connection could desynchronize the protocol stream.

Solutions

  1. Close/invalidate the connection and obtain a fresh one, then resend the command if idempotent
  2. Catch JedisConnectionException and treat the in-flight command as failed (no reliable reply)
  3. Check brokenCause to identify the initial failure (timeout, reset, closed socket)
  4. Avoid sharing a Connection across threads so errors are not interleaved

Example fix

// before
Object reply = connection.readProtocolCheckingBroken(); // broken
// after
try {
  Object reply = connection.readProtocolCheckingBroken();
} catch (JedisConnectionException e) {
  pool.returnBrokenResource(resource);
  resource = pool.getResource(); // retry command on new connection
}
Defensive patterns

Strategy: try-catch

Try / catch

try { reply = conn.readProtocolCheckingBroken(); } catch (JedisConnectionException e) { invalidate(conn); throw new CommandFailedException(cmd, e); }

Prevention

When it happens

Trigger: Calling getOne/readProtocol paths after an earlier write or read failure marked the connection broken; awaiting a reply for a command that was never (or only partially) written.

Common situations: Half-completed command round-trips after socket timeout; pub/sub or pipeline consumers reading after a network drop; connection reused across threads after one thread hit an error.

Related errors


AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08). Data as JSON: /api/errors/f556f190e92ac30f. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/redis/clients/jedis/Connection.java:781

    } catch (IOException ex) {
      throw markBroken(new JedisConnectionException(ex));
    } catch (Error err) {
      throw markBroken(err);
    }
  }

  @Experimental
  protected Object protocolRead(RedisInputStream is, PushConsumerChain consumer) {
    return Protocol.read(is, consumer);
  }

  @Experimental
  protected void protocolReadPushes(RedisInputStream is, PushConsumerChain consumer) {
  }

  protected Object readProtocolWithCheckingBroken() {
    if (broken) {
      throw new JedisConnectionException("Attempting to read from a broken connection.", brokenCause);
    }
    try {
      applyCurrentTimeout();
      return protocolRead(inputStream, pushConsumers);
    } catch (JedisDataException exc) {
      // Redis error reply was fully parsed; the stream is aligned and the connection reusable.
      throw exc;
    } catch (RuntimeException exc) {
      // Transport failures (JedisConnectionException) and any other unexpected failure mid-read
      // leave the stream position indeterminate.
      throw markBroken(exc);
    } catch (Error err) {
      throw markBroken(err);
    }
  }

  protected void readPushesWithCheckingBroken() {
    if (broken) {

View on GitHub (pinned to 6dac31d4c2)