dianping/cat · critical · RuntimeException
Unrecognized version(%s) for binary metric bag!
Error message
Unrecognized version(%s) for binary metric bag!
What it means
NativeMetricBagDecoder.decodeHeader reads a 3-byte version from an NM1 metric-bag payload and throws RuntimeException("Unrecognized version(%s) for binary metric bag!") unless it is literally 'NM1'. This validates the metric channel's protocol before reading domain/host/ip, analogous to the tree codec's header check.
Source
Thrown at cat-core/src/main/java/com/dianping/cat/message/codec/NativeMetricBagDecoder.java:42
bag.getMetrics().add(metric);
}
return bag;
}
private void decodeHeader(Context ctx, DefaultMetricBag bag) {
String version = ctx.readVersion();
if ("NM1".equals(version)) {
String domain = ctx.readString();
String hostName = ctx.readString();
String ipAddress = ctx.readString();
bag.setDomain(domain);
bag.setHostName(hostName);
bag.setIpAddress(ipAddress);
} else {
throw new RuntimeException(String.format("Unrecognized version(%s) for binary metric bag!", version));
}
}
private Metric decodeMetric(Context ctx) {
long timestamp = ctx.readLong();
String name = ctx.readString();
String kind = ctx.readString();
int count = ctx.readInt();
long sum = ctx.readLong();
long duration = ctx.readLong();
return new MyMetric(timestamp, name, kind, count, Double.longBitsToDouble(sum), duration);
}
private static class Context {
private static Charset UTF_8 = Charset.forName("UTF-8");
private ByteBuf m_buf;View on GitHub (pinned to e815e74d4c)
Solutions
- Hex-dump the payload's first three bytes; compare with 'NM1'.
- Pin cat-client and cat-core versions so the metric protocol tag matches.
- Fix the dispatch that routes buffers to NativeMetricBagDecoder — only NM1-tagged buffers belong there.
- Verify TCP framing delivers at least the 3 header bytes before decode is attempted.
Example fix
// before: dispatcher routes by port only if (isMetricPort) bag = metricDecoder.decode(buf); // tree arrives -> throws // after: dispatch by tag String tag = buf.toString(0, 3, UTF_8); MessageTree t = "NM1".equals(tag) ? decodeMetric(buf) : codecHandler.decode(buf);
Defensive patterns
Strategy: validation
Validate before calling
String tag = buf.toString(buf.readerIndex(), 3, CharsetUtil.UTF_8);
if (!"NM1".equals(tag)) { buf.release(); return; } Try / catch
catch (RuntimeException e) { if (e.getMessage().contains("binary metric bag")) { drop payload; log peer; } else throw e; } Prevention
- Dispatch by 3-byte tag, not by port or configuration guesses.
- Keep metric-channel clients version-aligned with the server.
When it happens
Trigger: A metric payload arrives with a version tag other than NM1 — newer client protocol, corrupted first 3 bytes, or a buffer routed to the metric decoder that was actually a PT1/NT1 message.
Common situations: Mixed client/server versions during upgrade; router/dispatcher bugs sending trees to the metric-bag decoder; truncated TCP payloads where the 3 header bytes are cut.
Related errors
- Unrecognized id(%s) for plain text message codec!
- Unsupported MetricType Name!
- Unrecognized version(%s) for binary message codec!
- Malformed variable int %s!
- Invalid level.
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/47550c8febaa474a.
Report an issue: GitHub.