YunaiV/ruoyi-vue-pro · error · RuntimeException
二进制消息解码失败: {}
Error message
二进制消息解码失败: {} What it means
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.
Source
Thrown at yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/serialize/binary/IotBinarySerializer.java:135
"消息长度不匹配,期望: " + messageLength + ", 实际: " + buffer.length());
// 5. 读取消息 ID
short messageIdLength = buffer.getShort(index);
index += 2;
String messageId = buffer.getString(index, index + messageIdLength, StandardCharsets.UTF_8.name());
index += messageIdLength;
// 6. 读取方法名
short methodLength = buffer.getShort(index);
index += 2;
String method = buffer.getString(index, index + methodLength, StandardCharsets.UTF_8.name());
index += methodLength;
// 7. 解析消息体
return parseMessageBody(buffer, index, messageType, messageId, method);
} catch (Exception e) {
log.error("[decode][二进制消息解码失败,数据长度: {}]", bytes.length, e);
throw new RuntimeException("二进制消息解码失败: " + e.getMessage(), e);
}
}
/**
* 快速检测是否为二进制格式
*
* @param data 数据
* @return 是否为二进制格式
*/
public static boolean isBinaryFormat(byte[] data) {
return data != null && data.length >= 1 && data[0] == MAGIC_NUMBER;
}
private byte determineMessageType(IotDeviceMessage message) {
if (message.getCode() != null) {
return RESPONSE;
}
return REQUEST;View on GitHub (pinned to 0418084e22)
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.
Example fix
// before
IotDeviceMessage msg = binarySerializer.deserialize(bytes); // RuntimeException on junk
// after
if (!IotBinarySerializer.isBinaryFormat(bytes)) {
// route to JSON deserializer instead
return jsonSerializer.deserialize(bytes);
}
IotDeviceMessage msg = binarySerializer.deserialize(bytes); Defensive patterns
Strategy: validation
Validate before calling
// Route by format BEFORE decoding
public IotDeviceMessage safeDeserialize(byte[] bytes, IotMessageSerializer binary, IotMessageSerializer json) {
if (!IotBinarySerializer.isBinaryFormat(bytes)) {
return json.deserialize(bytes);
}
return binary.deserialize(bytes);
} Type guard
public static boolean isBinaryFormat(byte[] data) {
return data != null && data.length >= 1 && data[0] == IotBinarySerializer.MAGIC_NUMBER;
} Try / catch
try {
return binarySerializer.deserialize(bytes);
} catch (RuntimeException e) {
log.warn("[decode][malformed binary frame, len={}]", bytes.length, e);
return null; // caller drops / dead-letters the datagram
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- 二进制消息编码失败: {}
- 未知的序列化类型:{}
- 序列化器({}) 不存在
- [createProtocol][协议实例 %s 的协议类型 %s 暂不支持]
- MQTT Client 启动失败: 连接 Broker 失败
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/081bafecd67c844f.
Report an issue: GitHub.