{"record":{"id":"5d2c2baf87cf882c","repo":"dianping/cat","slug":"unsupported-message-type-s-5d2c2b","errorCode":null,"errorMessage":"Unsupported message type(%s).","messagePattern":"Unsupported message type\\((.+?)\\)\\.","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"critical","filePath":"cat-core/src/main/java/com/dianping/cat/message/codec/NativeMessageCodec.java","lineNumber":92,"sourceCode":"\t\t\t\tMessage e = Codec.EVENT.decode(ctx, buf);\n\n\t\t\t\tctx.addChild(e);\n\t\t\t\tbreak;\n\t\t\tcase 'M':\n\t\t\t\tCodec.METRIC.decode(ctx, buf);\n\t\t\t\tbreak;\n\t\t\tcase 'H':\n\t\t\t\tMessage h = Codec.HEARTBEAT.decode(ctx, buf);\n\n\t\t\t\tctx.addChild(h);\n\t\t\t\tbreak;\n\t\t\tcase 'L':\n\t\t\t\tMessage l = Codec.TRACE.decode(ctx, buf);\n\n\t\t\t\tctx.addChild(l);\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tthrow new RuntimeException(String.format(\"Unsupported message type(%s).\", ch));\n\t\t\t}\n\t\t}\n\n\t\tif (msg == null) {\n\t\t\tmsg = ctx.getMessageTree().getMessage();\n\t\t}\n\n\t\treturn msg;\n\t}\n\n\t@Override\n\tpublic ByteBuf encode(MessageTree tree) {\n\t\tByteBuf buf = PooledByteBufAllocator.DEFAULT.buffer(4 * 1024);\n\n\t\ttry {\n\t\t\tContext ctx = new Context(tree);\n\n\t\t\tbuf.writeInt(0); // place-holder","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/dianping/cat/blob/e815e74d4c2dd74edac831241f1253fcc7d25381/cat-core/src/main/java/com/dianping/cat/message/codec/NativeMessageCodec.java#L74-L110","documentation":"In NativeMessageCodec.decode, each child message begins with a one-char tag: 't' transaction, 'T' transaction end, 'E' event, 'M' metric, 'H' heartbeat, 'L' trace. The default branch throws RuntimeException(\"Unsupported message type(%s).\" , ch) for any other character, meaning the byte stream is corrupt or misaligned — the decoder is reading where a type tag was expected.","triggerScenarios":"Decoding an NT1 buffer whose framing is broken: a truncated message, a payload truncated by TCP message-size limits, field-order mismatch between encoder/decoder versions, or a buffer accidentally double-decoded so the cursor sits on a data byte rather than a tag.","commonSituations":"Cat-client and cat-core protocol drift after partial upgrades; Netty frame decoders (DelimiterBased/LengthBased) misconfigured so messages split mid-record; payloads exceeding server-side max message size and being silently cut.","solutions":["Dump the buffer around the failure offset; verify the byte where decoding stopped is one of t/T/E/M/H/L.","Confirm encoder and decoder run the same NativeMessageCodec version on both ends (upgrade together).","Check the Netty pipeline framing (split frames, missing length-field prep) and the CAT server's max-message-size/child-message limits.","Guard against double-decode of the same ByteBuf (retain/release and readerIndex bugs)."],"exampleFix":"// before: no size guard, oversized tree arrives truncated\nserverSocketHandler.decode(buf); // mid-tree byte != tag -> throws\n\n// after: enforce same limits both ends\nint MAX = 8192; // align with server child-message cap\nif (tree.getMessages().size() > MAX) tree.getMessages().subList(MAX, tree.getMessages().size()).clear();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (RuntimeException e) { if (e.getMessage().startsWith(\"Unsupported message type\")) { log corrupt peer + offset; drop connection; } else throw e; }","preventionTips":["Use length-prefixed framing; never delimiter framing for binary CAT traffic.","Deploy client/server codec versions together.","Cap and test oversized message trees against the server's child limit."],"tags":["protocol","binary-decoding","netty","corruption"],"backgroundTag":null,"analyzedSha":"e815e74d4c2dd74edac831241f1253fcc7d25381","analyzedAt":"2026-08-14T14:22:34.512Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}