dianping/cat · critical · RuntimeException
Unrecognized id(%s) for plain text message codec!
Error message
Unrecognized id(%s) for plain text message codec!
What it means
PlainTextMessageCodec.decodeHeader validates the message-id token read from a PT1 payload against the expected VERSION constant and throws RuntimeException("Unrecognized id(%s) for plain text message codec!") on mismatch. The plain-text protocol begins with a version/id line; a different token means the payload is not a PT1 message this codec can parse.
Source
Thrown at cat-core/src/main/java/com/dianping/cat/message/codec/PlainTextMessageCodec.java:131
String threadName = helper.read(ctx, TAB);
String messageId = helper.read(ctx, TAB);
String parentMessageId = helper.read(ctx, TAB);
String rootMessageId = helper.read(ctx, TAB);
String sessionToken = helper.read(ctx, LF);
if (VERSION.equals(id)) {
tree.setDomain(domain);
tree.setHostName(hostName);
tree.setIpAddress(ipAddress);
tree.setThreadGroupName(threadGroupName);
tree.setThreadId(threadId);
tree.setThreadName(threadName);
tree.setMessageId(messageId);
tree.setParentMessageId(parentMessageId);
tree.setRootMessageId(rootMessageId);
tree.setSessionToken(sessionToken);
} else {
throw new RuntimeException(String.format("Unrecognized id(%s) for plain text message codec!", id));
}
}
protected Message decodeLine(Context ctx, DefaultTransaction parent, Stack<DefaultTransaction> stack,
MessageTree tree) {
BufferHelper helper = m_bufferHelper;
byte identifier = ctx.getBuffer().readByte();
String timestamp = helper.read(ctx, TAB);
String type = helper.read(ctx, TAB);
String name = helper.read(ctx, TAB);
switch (identifier) {
case 't':
DefaultTransaction transaction = new DefaultTransaction(type, name);
tree.findOrCreateTransactions().add(transaction);
helper.read(ctx, LF); // get rid of line feedView on GitHub (pinned to e815e74d4c)
Solutions
- Print the offending id from the exception; if it is 'NT1'/'NM1' the buffer was routed to the wrong codec.
- Route by the 3-byte tag before choosing plain-text vs native vs metric decoding (CodecHandler does this — bypassing it causes this error).
- Align client/server protocol versions.
- Check that the tab-delimited header line is intact (not truncated, no double encoding).
Example fix
// before PlainTextMessageCodec codec = ...; tree = codec.decode(buf); // buf actually starts 'NT1' -> throws // after MessageTree tree = new CodecHandler(plainCodec, nativeCodec, metricDecoder).decode(buf);
Defensive patterns
Strategy: validation
Validate before calling
String tag = buf.toString(buf.readerIndex(), 3, StandardCharsets.US_ASCII); MessageTree t = "PT1".equals(tag) ? plainCodec.decode(buf) : codecHandler.decode(buf);
Try / catch
catch (RuntimeException e) { if (e.getMessage().contains("plain text message codec")) { re-route buffer to CodecHandler.decode; } else throw e; } Prevention
- Always enter via CodecHandler; it performs tag dispatch for you.
- Smoke-test routing with PT1/NT1/NM1 sample payloads after pipeline changes.
When it happens
Trigger: Decoding a buffer whose header id token differs from VERSION — e.g. an NT1/NM1 binary payload reaching the plain-text codec, a corrupted header line, or a client with a different protocol revision.
Common situations: Wrong codec selected by a dispatcher; partial upgrades changing the id token; newline/tab framing issues that make the header token include stray bytes.
Related errors
- Unrecognized version(%s) for binary metric bag!
- Unrecognized version(%s) for binary message codec!
- Unknown identifier int name
- Invalid level.
- Unsupported MetricType Name!
AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14).
Data as JSON: /api/errors/355d7c9d0be371cb.
Report an issue: GitHub.