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
- 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
- If custom encoding is required, subclass the codec (PlainTextMessageCodec) and override encodeMessage to handle your type before delegating to super
- Filter out non-standard messages before flushing: skip children whose type is not Transaction/Event/Trace/Metric/Heartbeat when building the message tree
- 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
- Never attach custom Message implementations to a Transaction; use built-in Event/Metric types
- Add a compile-time constraint: factory methods that only return Transaction/Event/Trace/Metric/Heartbeat
- In integration tests, run a real encode pass over sample message trees to catch unsupported types early
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
- Invalid message ID format: %s
- Fail to create directory(%s)!
- Invalid index file: %s
- The date should be a string value
- Unsupported message type: %s.
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/1970282397428db6.
Report an issue: GitHub.