{"record":{"id":"b55245fe18efefbc","repo":"dianping/cat","slug":"error-message-type-s","errorCode":null,"errorMessage":"Error message type : %s","messagePattern":"Error message type : (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"cat-core/src/main/java/com/dianping/cat/message/CodecHandler.java","lineNumber":59,"sourceCode":"\t\tMessageTree tree;\n\n\t\tbuf.getBytes(4, data);\n\t\tString hint = new String(data);\n\n\t\tif (\"PT1\".equals(hint)) {\n\t\t\ttree = m_plainTextCodec.decode(buf);\n\t\t} else if (\"NT1\".equals(hint)) {\n\t\t\ttree = m_nativeCodec.decode(buf);\n\t\t} else if (\"NM1\".equals(hint)) {\n\t\t\tMetricBag bag = m_metricBagDecoder.decode(buf);\n\n\t\t\ttree = new DefaultMessageTree();\n\t\t\ttree.setDomain(bag.getDomain());\n\t\t\ttree.setIpAddress(bag.getIpAddress());\n\t\t\ttree.setHostName(bag.getHostName());\n\t\t\ttree.getMetrics().addAll(bag.getMetrics());\n\t\t} else {\n\t\t\tthrow new RuntimeException(\"Error message type : \" + hint);\n\t\t}\n\n\t\tMessageTreeFormat.format(tree);\n\t\treturn tree;\n\t}\n\n}\n","sourceCodeStart":41,"sourceCodeEnd":67,"githubUrl":"https://github.com/dianping/cat/blob/e815e74d4c2dd74edac831241f1253fcc7d25381/cat-core/src/main/java/com/dianping/cat/message/CodecHandler.java#L41-L67","documentation":"CodecHandler.decode dispatches on the 3-byte protocol hint at the start of an incoming message buffer: 'PT1' -> plain text, 'NT1' -> native binary, 'NM1' -> metric bag. Any other hint throws RuntimeException(\"Error message type : <hint>\"). This guard sits at the entry of server-side message decoding, so garbage or mismatched payloads fail here first.","triggerScenarios":"CodecHandler.decode(buf) where buf's first three bytes are not PT1/NT1/NM1: truncated payloads, random TCP data hitting the CAT port, an incompatible client protocol version, or a buffer whose readerIndex was not reset before decode.","commonSituations":"A load balancer / health probe connecting to the CAT receiver port and sending arbitrary bytes; old client speaking a retired protocol prefix; Netty ByteBuf reuse bugs where the reader index points mid-message.","solutions":["Hex-dump the first bytes of the failing buffer to see the actual hint string.","Verify client and server CAT versions agree on the wire protocol (PT1/NT1/NM1).","Ensure only CAT clients route to this port; keep health checks/probes off it or make them send nothing.","Check ByteBuf handling: slice/duplicate without resetting readerIndex, or reading the hint twice, will shift bytes and corrupt dispatch."],"exampleFix":"// before (double-read corrupts hint)\nString peek = buf.toString(0, 3, CharsetUtil.UTF_8);\ntree = handler.decode(buf); // readerIndex still at 0? maybe not\n\n// after\nbuf.resetReaderIndex();\ntree = handler.decode(buf);","handlingStrategy":"validation","validationCode":"String hint = buf.toString(buf.readerIndex(), 3, CharsetUtil.UTF_8);\nif (!(\"PT1\".equals(hint) || \"NT1\"equals(hint) || \"NM1\"equals(hint))) { buf.release(); return; /* drop */ }","typeGuard":null,"tryCatchPattern":"catch (RuntimeException e) { if (e.getMessage().startsWith(\"Error message type\")) { close connection; log peer address; } else throw e; }","preventionTips":["Restrict the CAT receiver port to CAT clients only.","Always route through CodecHandler rather than calling sub-codecs directly.","Reset readerIndex before decode when buffers are pre-inspected."],"tags":["protocol","network","decoding","netty"],"backgroundTag":null,"analyzedSha":"e815e74d4c2dd74edac831241f1253fcc7d25381","analyzedAt":"2026-08-14T14:22:34.512Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}