{"record":{"id":"42591cf75aeb0abb","repo":"redis/jedis","slug":"unknown-message-type-reply","errorCode":null,"errorMessage":"Unknown message type: <reply>","messagePattern":"Unknown message type: <reply>","errorType":"exception","errorClass":"JedisException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/JedisPubSubBase.java","lineNumber":198,"sourceCode":"          subscribedChannels = ((Long) listReply.get(2)).intValue();\n          final byte[] bpattern = (byte[]) listReply.get(1);\n          final T enpattern = (bpattern == null) ? null : encode(bpattern);\n          onPUnsubscribe(enpattern, subscribedChannels);\n        } else if (Arrays.equals(PONG.getRaw(), resp)) {\n          final byte[] bpattern = (byte[]) listReply.get(1);\n          final T enpattern = (bpattern == null) ? null : encode(bpattern);\n          onPong(enpattern);\n        } else {\n          throw new JedisException(\"Unknown message type: \" + firstObj);\n        }\n      } else if (reply instanceof byte[]) {\n        Consumer<Object> resultHandler = authenticator.resultHandler.poll();\n        if (resultHandler == null) {\n          throw new JedisException(\"Unexpected message : \" + SafeEncoder.encode((byte[]) reply));\n        }\n        resultHandler.accept(reply);\n      } else {\n        throw new JedisException(\"Unknown message type: \" + reply);\n      }\n    } while (!Thread.currentThread().isInterrupted() && isSubscribed());\n\n    //    /* Invalidate instance since this thread is no longer listening */\n    //    this.client = null;\n  }\n\n  private void processPingReply(Object reply) {\n    byte[] resp = (byte[]) reply;\n    if (\"PONG\".equals(SafeEncoder.encode(resp))) {\n      onPong(null);\n    } else {\n      onPong(encode(resp));\n    }\n  }\n}\n","sourceCodeStart":180,"sourceCodeEnd":215,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/JedisPubSubBase.java#L180-L215","documentation":"JedisPubSubBase.process() reads replies from the subscription loop and dispatches them by message type (subscribe ack, message, pong, etc.). When a reply arrives that does not match any known pub/sub reply shape, it throws JedisException(\"Unknown message type: \" + reply). It means the connection delivered an object the pub/sub state machine cannot interpret, usually a stray non-pub/sub reply on the subscription connection.","triggerScenarios":"Calling proceed()/proceedWithPatterns() on a connection whose reply stream contains a plain (non-array) object that is not a recognized pub/sub reply type, e.g. a plain byte[] status reply when no resultHandler is registered (that path is checked elsewhere) or a List whose first element is not a known command name byte[].","commonSituations":"Reusing a Jedis connection for subscribe while a pending command reply (e.g. AUTH or SELECT ack) is still unread; mixing a shared/pipelined connection into pub/sub; protocol desync after an error mid-handshake.","solutions":["Use a dedicated, freshly-obtained connection for pub/sub — never one with outstanding commands or unread replies.","Ensure subscribe/psubscribe is the first command issued on the pub/sub connection.","Check protocol version (RESP2 vs RESP3) matches what the pub/sub implementation expects.","Catch JedisException, close and re-create the subscription connection."],"exampleFix":"// before\nJedis j = pool.getResource();\nj.set(\"k\",\"v\");          // reply still pending\nnew JedisPubSubBase(j).proceed(channel); // desync -> Unknown message type\n// after\ntry (Jedis j = pool.getResource()) {\n  j.set(\"k\",\"v\");        // complete within try so reply consumed\n}\ntry (Jedis j = pool.getResource()) {\n  new JedisPubSubBase(j).proceed(channel); // clean connection\n}","handlingStrategy":"try-catch","validationCode":"if (jedis.isSubscribed() || jedis.isBroken()) { jedis.close(); jedis = pool.getResource(); }","typeGuard":"boolean isPubSubReply(Object reply) {\n  return reply instanceof List && !((List<?>) reply).isEmpty()\n      && ((List<?>) reply).get(0) instanceof byte[];\n}","tryCatchPattern":"try {\n  pubSub.proceed(jedis, channel);\n} catch (JedisException e) {\n  if (e.getMessage().startsWith(\"Unknown message type\")) {\n    jedis.close();\n    // re-subscribe on a fresh connection\n  } else throw e;\n}","preventionTips":["Always dedicate a fresh connection to pub/sub; subscribe must be the first command.","Consume/complete all prior command replies before entering the subscribe loop.","Never share the pub/sub connection across threads.","Keep client and server protocol (RESP2/RESP3) consistent."],"tags":["pubsub","protocol-desync","redis"],"backgroundTag":"unexpected-response-shape","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}