redis/jedis · error · JedisConnectionException

Bulk reply length is less than expected

Error message

Bulk reply length  is less than expected 

What it means

processBulkReply reads the declared bulk-string length; when a fixed prefix (skipBytes, e.g. verbatim-string prefix) must be skipped but the declared length is smaller than that prefix, the reply is malformed and JedisConnectionException is thrown. This indicates a protocol violation from the server.

Solutions

  1. Reset the connection; desynced streams corrupt subsequent length parsing.
  2. Verify the server is a genuine Redis instance supporting RESP3 verbatim strings.
  3. Capture the raw reply (tcpdump/wireshark or MONITOR) to inspect the malformed response.
  4. Upgrade Jedis and the server to aligned versions.

Example fix

// before (desynced shared connection)
Connection conn = sharedConnection; // used by two threads
conn.sendCommand(VERBATIM_CMD);

// after
try (Connection conn = pool.getResource()) { // dedicated connection per operation
  conn.sendCommand(VERBATIM_CMD);
}
Defensive patterns

Strategy: retry

Try / catch

try {
  return connection.executeCommand(cmd);
} catch (JedisConnectionException e) {
  connection.close(); // discard possibly desynced connection
  return retryOnFreshConnection(cmd);
}

Prevention

When it happens

Trigger: Receiving a bulk reply whose length header is smaller than the required prefix — practically only via processVerbatimStringReply (RESP3 verbatim strings, like from LOLWUT) where the server claims a length under 4.

Common situations: Non-conforming server implementations, corrupted network stream desync causing a length misread, or unusual RESP3-emitting proxies.

Related errors


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

Appendix: source

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

  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) {
      return null;
    }

    if (len < skipBytes) {
      throw new JedisConnectionException(
          "Bulk reply length " + len + " is less than expected " + skipBytes);
    }

    // Skip the prefix bytes
    for (int i = 0; i < skipBytes; i++) {
      is.readByte();
    }

    // Read the remaining data
    final int dataLen = len - skipBytes;
    final byte[] read = new byte[dataLen];
    int offset = 0;
    while (offset < dataLen) {
      final int size = is.read(read, offset, (dataLen - offset));
      if (size == -1) {
        throw new JedisConnectionException("It seems like server has closed the connection.");
      }
      offset += size;

View on GitHub (pinned to 6dac31d4c2)