redis/jedis · error · JedisException
Unknown message type
Error message
Unknown message type: <firstObj>
What it means
JedisShardedPubSubBase.process() expects each pub/sub reply to be a List whose first element is a byte[] naming the reply command (e.g. SSUBSCRIBE, SUNSUBSCRIBE, SMESSAGE). If the first element of the list is not a byte[], the reply type cannot be identified and it throws JedisException("Unknown message type: " + firstObj).
Solutions
- Use a clean dedicated connection for sharded pub/sub with SSUBSCRIBE as the first command.
- Verify RESP protocol setting (prefer RESP3) matches the server capability.
- Remove any proxy/middleware between client and Redis or ensure it preserves RESP framing.
- Catch JedisException and re-establish the subscription on a fresh connection.
Example fix
// before
Jedis j = pool.getResource();
j.xlen("stream"); // stale reply
shardedPubSub.ssubscribe(j, channel); // desync
// after
try (Jedis j = pool.getResource()) {
shardedPubSub.ssubscribe(j, channel); // first and only command on connection
} Defensive patterns
Strategy: try-catch
Validate before calling
// before subscribing ensure no pending replies
if (!jedis.getConnection().isBroken()) { /* ok */ } else { jedis.close(); } Type guard
boolean isShardedPubSubReply(Object reply) {
return reply instanceof List
&& ((List<?>) reply).get(0) instanceof byte[];
} Try / catch
try {
shardedPubSub.ssubscribe(jedis, channel);
} catch (JedisException e) {
if (e.getMessage().startsWith("Unknown message type")) {
jedis.close(); // fresh connection, re-subscribe
} else throw e;
} Prevention
- Issue SSUBSCRIBE as the first command on a dedicated connection.
- Use RESP3 for sharded pub/sub against Redis 7+.
- Avoid proxies that rewrite RESP framing.
- Upgrade Jedis when connecting to newer Redis servers.
When it happens
Trigger: proceed() loop receives a List reply whose element 0 is not a byte[] (e.g. a Long/complex RESP value) on the sharded pub/sub connection, indicating protocol desync or an unexpected server response.
Common situations: Using a connection with leftover replies before SSUBSCRIBE; server/protocol mismatch (RESP3 push frames interpreted oddly); custom proxies or RESP translators reshaping replies.
Related errors
- Unexpected message
- Unknown message type
- Blocking pub/sub operations are not supported on…
- Unknown message type
- Unexpected message
AI-assisted analysis of redis/jedis@6dac31d4c2 (2026-09-08).
Data as JSON: /api/errors/a39e7b14d7dd3ce0.
Report an issue: GitHub.
Appendix: source
Thrown at src/main/java/redis/clients/jedis/JedisShardedPubSubBase.java:84
process();
} finally {
authenticator.client.setActiveSubscription(false);
authenticator.client.rollbackTimeout();
}
}
protected abstract T encode(byte[] raw);
private void process() {
do {
Object reply = authenticator.client.getUnflushedObject();
if (reply instanceof List) {
List<Object> listReply = (List<Object>) reply;
final Object firstObj = listReply.get(0);
if (!(firstObj instanceof byte[])) {
throw new JedisException("Unknown message type: " + firstObj);
}
final byte[] resp = (byte[]) firstObj;
if (Arrays.equals(SSUBSCRIBE.getRaw(), resp)) {
subscribedChannels = ((Long) listReply.get(2)).intValue();
final byte[] bchannel = (byte[]) listReply.get(1);
final T enchannel = (bchannel == null) ? null : encode(bchannel);
onSSubscribe(enchannel, subscribedChannels);
} else if (Arrays.equals(SUNSUBSCRIBE.getRaw(), resp)) {
subscribedChannels = ((Long) listReply.get(2)).intValue();
final byte[] bchannel = (byte[]) listReply.get(1);
final T enchannel = (bchannel == null) ? null : encode(bchannel);
onSUnsubscribe(enchannel, subscribedChannels);
} else if (Arrays.equals(SMESSAGE.getRaw(), resp)) {
final byte[] bchannel = (byte[]) listReply.get(1);
final byte[] bmesg = (byte[]) listReply.get(2);
final T enchannel = (bchannel == null) ? null : encode(bchannel);
final T enmesg = (bmesg == null) ? null : encode(bmesg);
onSMessage(enchannel, enmesg);View on GitHub (pinned to 6dac31d4c2)