redis/jedis · critical · JedisConnectionException

Unknown reply:

Error message

Unknown reply: 

What it means

Protocol.process() reads the first byte of a Redis reply and dispatches on the RESP type. If the byte is not one of the known reply markers (+, -, :, $, *, _, #, etc.), it throws JedisConnectionException "Unknown reply: X", meaning the bytes on the wire are not a valid RESP reply.

Solutions

  1. Verify the host/port points to a real Redis server (run redis-cli -h host -p port PING).
  2. Reset/recreate the connection if a desync occurred; never share a Connection across threads.
  3. Check for middleboxes/proxies or TLS misconfiguration returning HTML or plain text.
  4. Upgrade Jedis — new Redis reply types can be unknown to older client versions.

Example fix

// before
Jedis jedis = new Jedis("myapp.internal", 443); // plain-text proxy replies -> Unknown reply

// after
Jedis jedis = new Jedis("redis.internal", 6379); // correct Redis host/port, or use ssl=true for TLS endpoints
Defensive patterns

Strategy: try-catch

Validate before calling

// before connecting, sanity-check the endpoint answers like Redis
// e.g. run: redis-cli -h host -p port PING  -> expect PONG

Try / catch

try {
  return jedis.get(key);
} catch (JedisConnectionException e) {
  if (e.getMessage() != null && e.getMessage().startsWith("Unknown reply")) {
    // stream desync or non-Redis endpoint: discard connection, verify endpoint, reconnect
    jedis.close();
  }
  throw e;
}

Prevention

When it happens

Trigger: Deserializing a reply whose leading byte is unrecognized: responses to unknown protocol input, corrupted stream desynchronization (e.g. reading a reply mid-stream), or an unexpected char such as 'C'/'O' from a non-Redis or proxy endpoint.

Common situations: Pointing the client at something that is not a Redis server, a proxy (HAProxy/Caddy) emitting plain text, RESP3/push-message desync, or custom scripts intercepting traffic.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at src/main/java/redis/clients/jedis/Protocol.java:175

          return processMultiBulkReply(is);
        case GREATER_THAN_BYTE:
          // Process push message through the consumer chain
          PushMessage message = processPush(is, pushConsumer);
          if (message != null) {
            // Message not consumed by PushConsumers - propagate to application
            // This preserves backward compatibility by allowing applications to handle
            // push messages that aren't consumed by internal consumers
            return message.getContent();
          } else {
            // Message was consumed by PushConsumers - continue reading next
            break;
          }
        case MINUS_BYTE:
          processError(is);
          return null;
        // TODO: Blob error '!'
        default:
          throw new JedisConnectionException("Unknown reply: " + (char) b);
      }
    } while (true);

  }

  private static byte[] processBulkReply(final RedisInputStream is) {
    return processBulkReply(is, 0);
  }

  /**
   * Process a bulk reply, optionally skipping a prefix.
   * @param is the input stream
   * @param skipBytes number of bytes to skip at the beginning (used for verbatim strings)
   * @return the bulk reply data (excluding skipped bytes), or null if length is -1
   */
  private static byte[] processBulkReply(final RedisInputStream is, final int skipBytes) {
    final int len = is.readIntCrLf();
    if (len == -1) {

View on GitHub (pinned to 6dac31d4c2)