{"record":{"id":"081bafecd67c844f","repo":"YunaiV/ruoyi-vue-pro","slug":"error-081baf","errorCode":null,"errorMessage":"二进制消息解码失败: {}","messagePattern":"二进制消息解码失败: (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/serialize/binary/IotBinarySerializer.java","lineNumber":135,"sourceCode":"                    \"消息长度不匹配，期望: \" + messageLength + \", 实际: \" + buffer.length());\n\n            // 5. 读取消息 ID\n            short messageIdLength = buffer.getShort(index);\n            index += 2;\n            String messageId = buffer.getString(index, index + messageIdLength, StandardCharsets.UTF_8.name());\n            index += messageIdLength;\n\n            // 6. 读取方法名\n            short methodLength = buffer.getShort(index);\n            index += 2;\n            String method = buffer.getString(index, index + methodLength, StandardCharsets.UTF_8.name());\n            index += methodLength;\n\n            // 7. 解析消息体\n            return parseMessageBody(buffer, index, messageType, messageId, method);\n        } catch (Exception e) {\n            log.error(\"[decode][二进制消息解码失败，数据长度: {}]\", bytes.length, e);\n            throw new RuntimeException(\"二进制消息解码失败: \" + e.getMessage(), e);\n        }\n    }\n\n    /**\n     * 快速检测是否为二进制格式\n     *\n     * @param data 数据\n     * @return 是否为二进制格式\n     */\n    public static boolean isBinaryFormat(byte[] data) {\n        return data != null && data.length >= 1 && data[0] == MAGIC_NUMBER;\n    }\n\n    private byte determineMessageType(IotDeviceMessage message) {\n        if (message.getCode() != null) {\n            return RESPONSE;\n        }\n        return REQUEST;","sourceCodeStart":117,"sourceCodeEnd":153,"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/serialize/binary/IotBinarySerializer.java#L117-L153","documentation":"IotBinarySerializer.deserialize wraps any Exception thrown while parsing an incoming byte array — magic-number check, length guard, messageId read, method-length/method read, and parseMessageBody — and rethrows as a RuntimeException. It is distinct from the up-front asserts (Assert.notNull bytes, Assert.isTrue bytes.length >= MIN_MESSAGE_LENGTH) which fail before the try block. So this wrapped error means the packet cleared the minimum-length check but failed structural parsing afterward.","triggerScenarios":"Feeding bytes that do not actually start with MAGIC_NUMBER but are long enough; a truncated/corrupt frame (methodLength shorter than remaining buffer, or charset decode failure); a packet from a device speaking a different binary protocol version; network-layer delivering a partial datagram. Note isBinaryFormat(data) is the intended pre-filter and should gate calls to deserialize.","commonSituations":"A JSON payload mistakenly routed into the binary deserializer; protocol version mismatch between device firmware and gateway; bit flips on lossy transport; sending test/garbage bytes through the binary path.","solutions":["Call IotBinarySerializer.isBinaryFormat(bytes) (checks data[0] == MAGIC_NUMBER) before deserialize to route packets to the correct serializer.","Inspect the logged cause and bytes.length — the '[decode][二进制消息解码失败' log line prints both.","Validate the packet at the protocol boundary: magic byte, then total length against the declared messageId/method lengths.","Drop or quarantine malformed frames at the UDP handler and log the device address rather than propagating the RuntimeException."],"exampleFix":"// before\nIotDeviceMessage msg = binarySerializer.deserialize(bytes); // RuntimeException on junk\n\n// after\nif (!IotBinarySerializer.isBinaryFormat(bytes)) {\n    // route to JSON deserializer instead\n    return jsonSerializer.deserialize(bytes);\n}\nIotDeviceMessage msg = binarySerializer.deserialize(bytes);","handlingStrategy":"validation","validationCode":"// Route by format BEFORE decoding\npublic IotDeviceMessage safeDeserialize(byte[] bytes, IotMessageSerializer binary, IotMessageSerializer json) {\n    if (!IotBinarySerializer.isBinaryFormat(bytes)) {\n        return json.deserialize(bytes);\n    }\n    return binary.deserialize(bytes);\n}","typeGuard":"public static boolean isBinaryFormat(byte[] data) {\n    return data != null && data.length >= 1 && data[0] == IotBinarySerializer.MAGIC_NUMBER;\n}","tryCatchPattern":"try {\n    return binarySerializer.deserialize(bytes);\n} catch (RuntimeException e) {\n    log.warn(\"[decode][malformed binary frame, len={}]\", bytes.length, e);\n    return null; // caller drops / dead-letters the datagram\n}","preventionTips":["Always gate binary deserialize with isBinaryFormat(bytes) (magic-byte check).","Reject packets shorter than MIN_MESSAGE_LENGTH before calling deserialize.","Validate methodLength against remaining buffer when extending the protocol.","Quarantine and log malformed frames rather than propagating the exception up the Vert.x handler."],"tags":["iot","serialization","binary-protocol","decoding","input-validation"],"backgroundTag":null,"analyzedSha":"0418084e222612af2fc1141f566af454f9236ab1","analyzedAt":"2026-08-14T00:56:18.412Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}