YunaiV/ruoyi-vue-pro · error · RuntimeException
[createDecodeParser][解析异常]
Error message
[createDecodeParser][解析异常]
What it means
The Vert.x RecordParser.exceptionHandler for the length-field codec rethrows any parser error as RuntimeException. Unlike the delimiter codec, the length-field codec also performs its own state-machine throws (errors 54/55), but those throw directly inside the handler, not via exceptionHandler. This handler catches Vert.x parser-level errors — typically a record exceeding MAX_FRAME_LENGTH (64KB) when the decoded body length is huge.
Source
Thrown at yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/codec/length/IotTcpLengthFieldFrameCodec.java:106
}
// 【重要】切换到读取消息体模式
bodyLength.set(frameBodyLength);
parser.fixedSizeMode(frameBodyLength);
} else {
// 阶段 2: 读取消息体,组装完整帧
Buffer frame = processFrame(headerBuffer.get(), buffer);
// 重置状态,准备读取下一帧
bodyLength.set(null);
headerBuffer.set(null);
parser.fixedSizeMode(headerLength);
// 【重要】处理完整消息
handler.handle(frame);
}
});
parser.exceptionHandler(ex -> {
throw new RuntimeException("[createDecodeParser][解析异常]", ex);
});
return parser;
}
@Override
public Buffer encode(byte[] data) {
Buffer buffer = Buffer.buffer();
// 计算要写入的长度值
int lengthValue = data.length - lengthAdjustment;
// 写入偏移量前的填充字节(如果有)
for (int i = 0; i < lengthFieldOffset; i++) {
buffer.appendByte((byte) 0);
}
// 写入长度字段
writeLength(buffer, lengthValue, lengthFieldLength);
// 写入消息体
buffer.appendBytes(data);
return buffer;View on GitHub (pinned to 0418084e22)
Solutions
- Add an UPPER bound check on frameBodyLength (e.g. > MAX_FRAME_LENGTH) before calling parser.fixedSizeMode(frameBodyLength), so oversized frames are rejected explicitly instead of letting the parser error.
- Verify lengthFieldOffset/lengthFieldLength/lengthAdjustment match the device spec.
- Log the cause and close the socket rather than rethrowing on the event loop.
Example fix
// before: only negative/zero checked; huge length slips through to the parser
parser.fixedSizeMode(frameBodyLength);
// after: also bound the maximum
if (frameBodyLength > MAX_FRAME_LENGTH) {
throw new IllegalStateException("frame body too large: " + frameBodyLength);
}
parser.fixedSizeMode(frameBodyLength); Defensive patterns
Strategy: try-catch
Validate before calling
// bound the decoded body length before switching the parser mode
if (frameBodyLength < 0) { throw new IllegalStateException("帧长度异常: " + frameBodyLength); }
if (frameBodyLength == 0) { throw new IllegalStateException("消息体不能为空"); }
if (frameBodyLength > MAX_FRAME_LENGTH) {
throw new IllegalStateException("帧长度超过上限: " + frameBodyLength);
} Try / catch
// log + close the socket instead of rethrowing on the event loop
parser.exceptionHandler(ex -> {
log.error("[createDecodeParser][解析异常]", ex);
socket.close();
}); Prevention
- Add an upper-bound check on frameBodyLength so a misread/malicious huge length is rejected explicitly, not by the parser.
- Verify lengthFieldOffset/lengthFieldLength/lengthAdjustment match the device spec.
- Do not rethrow inside exceptionHandler; log and close the offending socket.
- Monitor parse failures per connection to detect DoS or misconfigured devices.
When it happens
Trigger: A malformed length field causes the parser to switch to a huge fixedSizeMode that crosses 64KB (maxRecordSize) and the parser fires its exception handler; a device sends a deliberately oversized length (DoS); parser internal error.
Common situations: Length field misread (wrong offset/length) yielding a giant body size; malicious oversized-length attack; the negative/zero guards (errors 54/55) pass but the value is still unreasonably large.
Related errors
- [createDecodeParser][解析异常]
- [createDecodeParser][解析异常]
- [createDecodeParser][帧长度异常,length: %d, frameBodyLength: %d]
- [createDecodeParser][消息体不能为空]
- 不支持的长度字段长度: {}
AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14).
Data as JSON: /api/errors/92c5997e45b49b39.
Report an issue: GitHub.