dianping/cat · error · RuntimeException

Unsupported message( ).

Error message

Unsupported message(%s).

What it means

NativeMessageCodec's encodeMessage throws RuntimeException("Unsupported message(%s).") — note it interpolates msg.toString(), not the class — when the object to encode is none of Transaction/Event/Metric/Heartbeat/Trace. This is the encode-side twin of the decode-side type-tag guard: the binary wire format simply has no tag for other Message implementations.

Solutions

  1. Read the object description in the exception message to identify which child is unsupported.
  2. Replace the custom implementation with DefaultEvent/DefaultTransaction/etc. so the standard tags apply.
  3. Sanitize the tree before send: drop or convert unknown message kinds.
  4. Upgrade CAT on both sides if a legitimate newer message type is involved.

Example fix

// before
Message raw = mock(Message.class); // not a known subtype
codec.encode(treeWith(raw)); // throws

// after
DefaultEvent ev = new DefaultEvent("Custom", "value");
codec.encode(treeWith(ev)); // 'E' tag
Defensive patterns

Strategy: type-guard

Validate before calling

List<Message> keep = new ArrayList<>();
for (Message m : tree.getMessages())
    if (m instanceof Transaction || m instanceof Event || m instanceof Metric || m instanceof Heartbeat || m instanceof Trace) keep.add(m);
tree.getMessages().retainAll(keep);

Type guard

boolean encodable(Message m) { return m instanceof Transaction || m instanceof Event || m instanceof Metric || m instanceof Heartbeat || m instanceof Trace; }

Prevention

When it happens

Trigger: Encoding a MessageTree whose children contain a bare Message implementation (mock, proxy, or plugin class) rather than one of the five built-in kinds; the toString() in the message identifies the offending object.

Common situations: Unit tests with mocked Message objects fed into the real codec; custom message classes from home-grown extensions; objects wrapped by dynamic proxies (AOP) that no longer instanceOf the known types.

Related errors


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

Appendix: source

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

			Codec.TRANSACTION_START.encode(ctx, buf, msg);

			for (Message child : children) {
				if (child != null) {
					encodeMessage(ctx, buf, child);
				}
			}

			Codec.TRANSACTION_END.encode(ctx, buf, msg);
		} else if (msg instanceof Event) {
			Codec.EVENT.encode(ctx, buf, msg);
		} else if (msg instanceof Metric) {
			Codec.METRIC.encode(ctx, buf, msg);
		} else if (msg instanceof Heartbeat) {
			Codec.HEARTBEAT.encode(ctx, buf, msg);
		} else if (msg instanceof Trace) {
			Codec.TRACE.encode(ctx, buf, msg);
		} else {
			throw new RuntimeException(String.format("Unsupported message(%s).", msg));
		}
	}

	enum Codec {
		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));

View on GitHub (pinned to e815e74d4c)