dianping/cat · error · RuntimeException

Unsupported message type: %s.

Error message

Unsupported message type: %s.

What it means

This RuntimeException is thrown by PlainTextMessageCodec.encodeMessage when a Message object passed to the plain-text encoder is not one of the five supported concrete types: Transaction, Event, Trace, Metric, or Heartbeat. The codec iterates instanceof checks (each mapped to a letter tag: t/T/A, E, L, M, H) and any custom or unknown Message implementation falls through to the else branch. It exists because the wire protocol only defines encodings for those five types, so a custom Message subtype cannot be serialized.

Source

Thrown at cat-core/src/main/java/com/dianping/cat/message/codec/PlainTextMessageCodec.java:413

					if (child != null) {
						count += encodeMessage(child, buf);
					}
				}

				count += encodeLine(transaction, buf, 'T', Policy.WITH_DURATION);

				return count;
			}
		} else if (message instanceof Event) {
			return encodeLine(message, buf, 'E', Policy.DEFAULT);
		} else if (message instanceof Trace) {
			return encodeLine(message, buf, 'L', Policy.DEFAULT);
		} else if (message instanceof Metric) {
			return encodeLine(message, buf, 'M', Policy.DEFAULT);
		} else if (message instanceof Heartbeat) {
			return encodeLine(message, buf, 'H', Policy.DEFAULT);
		} else {
			throw new RuntimeException(String.format("Unsupported message type: %s.", message));
		}
	}

	protected void setBufferWriter(BufferWriter writer) {
		m_writer = writer;
		m_bufferHelper = new BufferHelper(m_writer);
	}

	protected static enum Policy {
		DEFAULT,

		WITHOUT_STATUS,

		WITH_DURATION;

		public static Policy getByMessageIdentifier(byte identifier) {
			switch (identifier) {
			case 't':

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Replace the custom Message implementation with one of the built-in types (usually Event via new DefaultEvent(...) or Cat.logEvent) so the encoder recognizes it
  2. If custom encoding is required, subclass the codec (PlainTextMessageCodec) and override encodeMessage to handle your type before delegating to super
  3. Filter out non-standard messages before flushing: skip children whose type is not Transaction/Event/Trace/Metric/Heartbeat when building the message tree
  4. Verify what object is actually reaching the codec by logging message.getClass() at the call site that constructs the tree

Example fix

// before
class MyCustomMessage implements Message { ... }
transaction.addChild(new MyCustomMessage());

// after
Event event = new DefaultEvent();
event.setType("MyType");
event.setName("my-event");
event.setStatus(Message.SUCCESS);
transaction.addChild(event);
Defensive patterns

Strategy: type-guard

Validate before calling

boolean encodable = m instanceof Transaction || m instanceof Event
        || m instanceof Trace || m instanceof Metric || m instanceof Heartbeat;
if (!encodable) {
    // log and skip instead of feeding to the codec
    logger.warn("Skipping unsupported message type: " + m.getClass().getName());
}

Type guard

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

Try / catch

try {
    codec.encodeMessage(message, buf);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("Unsupported message type")) {
        logger.warn("Dropping unencodable message " + message.getClass().getName(), e);
    } else {
        throw e;
    }
}

Prevention

When it happens

Trigger: Calling encodeMessage (directly or via a transport/channel that uses PlainTextMessageCodec) with a custom class implementing com.dianping.cat.message.Message that does not extend/implement Transaction, Event, Trace, Metric, or Heartbeat. Also triggered when a Transaction child list contains such a custom message (children are recursively encoded at line 396), or when a mock/test Message is attached to a real Transaction that gets flushed to the CAT server.

Common situations: Developers extend the Message interface to add domain-specific fields and then log it through Cat.log(...) or add it as a transaction child; upgrading CAT versions where a previously tolerated type is no longer handled; unit tests injecting hand-rolled Message fakes into a real codec pipeline.

Related errors


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