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

  1. 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.
  2. Verify lengthFieldOffset/lengthFieldLength/lengthAdjustment match the device spec.
  3. 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

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


AI-assisted analysis of YunaiV/ruoyi-vue-pro@0418084e22 (2026-08-14). Data as JSON: /api/errors/92c5997e45b49b39. Report an issue: GitHub.