dianping/cat · critical · RuntimeException

Unrecognized version(%s) for binary message codec!

Error message

Unrecognized version(%s) for binary message codec!

What it means

The HEADER codec of NativeMessageCodec reads a version string at the start of every NT1 binary tree and throws RuntimeException("Unrecognized version(%s) for binary message codec!") unless it equals the expected ID constant. Any client emitting a different header string (older/newer protocol revision) is rejected before any field decoding.

Source

Thrown at cat-core/src/main/java/com/dianping/cat/message/codec/NativeMessageCodec.java:177

		HEADER {
			@Override
			protected Message decode(Context ctx, ByteBuf buf) {
				MessageTree tree = ctx.getMessageTree();
				String version = ctx.getVersion(buf);

				if (ID.equals(version)) {
					tree.setDomain(ctx.readString(buf));
					tree.setHostName(ctx.readString(buf));
					tree.setIpAddress(ctx.readString(buf));
					tree.setThreadGroupName(ctx.readString(buf));
					tree.setThreadId(ctx.readString(buf));
					tree.setThreadName(ctx.readString(buf));
					tree.setMessageId(ctx.readString(buf));
					tree.setParentMessageId(ctx.readString(buf));
					tree.setRootMessageId(ctx.readString(buf));
					tree.setSessionToken(ctx.readString(buf));
				} else {
					throw new RuntimeException(String.format("Unrecognized version(%s) for binary message codec!", version));
				}

				return null;
			}

			@Override
			protected void encode(Context ctx, ByteBuf buf, Message msg) {
				MessageTree tree = ctx.getMessageTree();

				ctx.writeVersion(buf, ID);
				ctx.writeString(buf, tree.getDomain());
				ctx.writeString(buf, tree.getHostName());
				ctx.writeString(buf, tree.getIpAddress());
				ctx.writeString(buf, tree.getThreadGroupName());
				ctx.writeString(buf, tree.getThreadId());
				ctx.writeString(buf, tree.getThreadName());
				ctx.writeString(buf, tree.getMessageId());
				ctx.writeString(buf, tree.getParentMessageId());

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Capture the version string from the exception — it shows exactly what the peer sent.
  2. Align client and server versions (upgrade/downgrade so both use the same NT1 header contract).
  3. During rolling upgrades, keep protocol-compatible versions overlapping or drain old clients first.
  4. Verify Netty framing so the version bytes are read from offset 0 of the message.

Example fix

# before
client 3.1.x (header v1) -> server 2.x (expects older ID): throws

# after
upgrade all cat-clients to match cat-core version, e.g. both on 3.1.x: NT1 header accepted
Defensive patterns

Strategy: validation

Validate before calling

String tag = buf.toString(0, 3, StandardCharsets.US_ASCII);
if (!"NT1".equals(tag)) reject("expected NT1 header, got " + tag);

Try / catch

catch (RuntimeException e) { if (e.getMessage().contains("Unrecognized version")) { log peer version from message; isolate/upgrade node; } else throw e; }

Prevention

When it happens

Trigger: A cat-client with a different binary header version sends trees to a cat-core whose NativeMessageCodec.ID does not match; or the buffer is misframed so the 'version' read picks up non-header bytes.

Common situations: Mixed-version CAT clusters (old client, new server or vice versa) during rolling upgrades; hot-redeploy of one side only; framed-pipeline bugs that shift the reader index before decode.

Related errors


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/c6e2267a86dc696a. Report an issue: GitHub.