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

  1. Hex-dump the payload's first three bytes; compare with 'NM1'.
  2. Pin cat-client and cat-core versions so the metric protocol tag matches.
  3. Fix the dispatch that routes buffers to NativeMetricBagDecoder — only NM1-tagged buffers belong there.
  4. 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

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


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