{"record":{"id":"33b4a45c7af46ac2","repo":"YunaiV/ruoyi-vue-pro","slug":"createdecodeparser-33b4a4","errorCode":null,"errorMessage":"[createDecodeParser][消息体不能为空]","messagePattern":"\\[createDecodeParser\\]\\[消息体不能为空\\]","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"warning","filePath":"yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/codec/length/IotTcpLengthFieldFrameCodec.java","lineNumber":87,"sourceCode":"        final AtomicReference<Integer> bodyLength = new AtomicReference<>(null); // 消息体长度，null 表示读取头部阶段\n        final AtomicReference<Buffer> headerBuffer = new AtomicReference<>(null); // 头部消息\n\n        // 处理读取到的数据\n        parser.handler(buffer -> {\n            if (bodyLength.get() == null) {\n                // 阶段 1: 读取头部，解析长度字段\n                headerBuffer.set(buffer.copy());\n                int length = readLength(buffer, lengthFieldOffset, lengthFieldLength);\n                int frameBodyLength = length + lengthAdjustment;\n                // 检查帧长度是否合法\n                if (frameBodyLength < 0) {\n                    throw new IllegalStateException(String.format(\n                            \"[createDecodeParser][帧长度异常，length: %d, frameBodyLength: %d]\",\n                            length, frameBodyLength));\n                }\n                // 消息体为空，抛出异常\n                if (frameBodyLength == 0) {\n                    throw new IllegalStateException(\"[createDecodeParser][消息体不能为空]\");\n                }\n\n                // 【重要】切换到读取消息体模式\n                bodyLength.set(frameBodyLength);\n                parser.fixedSizeMode(frameBodyLength);\n            } else {\n                // 阶段 2: 读取消息体，组装完整帧\n                Buffer frame = processFrame(headerBuffer.get(), buffer);\n                // 重置状态，准备读取下一帧\n                bodyLength.set(null);\n                headerBuffer.set(null);\n                parser.fixedSizeMode(headerLength);\n\n                // 【重要】处理完整消息\n                handler.handle(frame);\n            }\n        });\n        parser.exceptionHandler(ex -> {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/YunaiV/ruoyi-vue-pro/blob/0418084e222612af2fc1141f566af454f9236ab1/yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/codec/length/IotTcpLengthFieldFrameCodec.java#L69-L105","documentation":"During length-field decoding, after computing frameBodyLength = readLength(...) + lengthAdjustment, a result of exactly ZERO is rejected as an empty body. This fires when the decoded length field plus adjustment equals zero — the device sent a zero-length body, or lengthAdjustment cancels out a legitimate small length value.","triggerScenarios":"Device sends length=0 with adjustment=0; lengthAdjustment configured to exactly negate a legitimate length value (e.g. length includes header bytes and adjustment subtracts them, netting zero for small frames); device emits a valid heartbeat/keepalive frame with no body that this codec rejects.","commonSituations":"Misconfigured lengthAdjustment; device protocol legitimately allows zero-body control/heartbeat frames; device firmware bug emitting length=0.","solutions":["Confirm lengthAdjustment matches the protocol — often 0 when the length field already represents the body size.","If zero-body frames are valid in your protocol, relax the codec to handle frameBodyLength==0 (emit an empty body to the handler instead of throwing).","Check the device isn't emitting a malformed length due to a firmware bug (capture traffic)."],"exampleFix":"// before: zero-length body throws\nif (frameBodyLength == 0) {\n    throw new IllegalStateException(\"[createDecodeParser][消息体不能为空]\");\n}\n\n// after: allow zero-body frames if your protocol supports them\nif (frameBodyLength == 0) {\n    Buffer frame = processFrame(headerBuffer.get(), Buffer.buffer());\n    bodyLength.set(null);\n    headerBuffer.set(null);\n    parser.fixedSizeMode(headerLength);\n    handler.handle(frame);\n    return;\n}","handlingStrategy":"validation","validationCode":"// confirm lengthAdjustment matches the protocol before deploying\n// most commonly 0 when the length field already encodes body size\nif (lengthAdjustment != 0) {\n    log.warn(\"lengthAdjustment={}, 确认与设备协议一致\", lengthAdjustment);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Confirm lengthAdjustment against the device datasheet (often 0).","If the protocol allows zero-body frames (heartbeats), relax the codec to emit an empty body instead of throwing.","Capture traffic to confirm whether length=0 is a device bug or a valid control frame."],"tags":["tcp","codec","length-field","validation"],"backgroundTag":null,"analyzedSha":"0418084e222612af2fc1141f566af454f9236ab1","analyzedAt":"2026-08-14T00:56:18.412Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}