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
- Capture the version string from the exception — it shows exactly what the peer sent.
- Align client and server versions (upgrade/downgrade so both use the same NT1 header contract).
- During rolling upgrades, keep protocol-compatible versions overlapping or drain old clients first.
- 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
- Keep the whole CAT fleet on one version during rolling upgrades.
- Log the reported version string to identify the offending client quickly.
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
- Unsupported message type(%s).
- Malformed variable int %s!
- Unrecognized version(%s) for binary metric bag!
- Unrecognized id(%s) for plain text message codec!
- Invalid level.
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/c6e2267a86dc696a.
Report an issue: GitHub.