YunaiV/ruoyi-vue-pro · error · RuntimeException

[createDecodeParser][解析异常]

Error message

[createDecodeParser][解析异常]

What it means

The Vert.x RecordParser.exceptionHandler for the delimiter-based codec rethrows any parser error as RuntimeException. For this codec the realistic trigger is a record exceeding MAX_RECORD_SIZE (64KB): a device streams data without ever emitting the configured delimiter, so the parser buffers past the cap and fires the exception handler.

Source

Thrown at yudao-module-iot/yudao-module-iot-gateway/src/main/java/cn/iocoder/yudao/module/iot/gateway/protocol/tcp/codec/delimiter/IotTcpDelimiterFrameCodec.java:58

    public IotTcpDelimiterFrameCodec(IotTcpConfig.CodecConfig config) {
        Assert.notBlank(config.getDelimiter(), "delimiter 不能为空");
        this.delimiterBytes = parseDelimiter(config.getDelimiter());
    }

    @Override
    public IotTcpCodecTypeEnum getType() {
        return IotTcpCodecTypeEnum.DELIMITER;
    }

    @Override
    public RecordParser createDecodeParser(Handler<Buffer> handler) {
        RecordParser parser = RecordParser.newDelimited(Buffer.buffer(delimiterBytes));
        parser.maxRecordSize(MAX_RECORD_SIZE); // 设置最大记录大小,防止 DoS 攻击
        // 处理完整消息(不包含分隔符)
        parser.handler(handler);
        parser.exceptionHandler(ex -> {
            throw new RuntimeException("[createDecodeParser][解析异常]", ex);
        });
        return parser;
    }

    @Override
    public Buffer encode(byte[] data) {
        Buffer buffer = Buffer.buffer();
        buffer.appendBytes(data);
        buffer.appendBytes(delimiterBytes);
        return buffer;
    }

    /**
     * 解析分隔符字符串为字节数组
     * <p>
     * 支持转义字符:\n、\r、\r\n、\t
     *
     * @param delimiter 分隔符字符串

View on GitHub (pinned to 0418084e22)

Solutions

  1. Confirm the configured delimiter (config.delimiter, supporting \n \r \r\n \t or custom) exactly matches the device's frame terminator — capture traffic with Wireshark/tcpdump to verify.
  2. If legitimate frames exceed 64KB, raise MAX_RECORD_SIZE (and ensure memory headroom).
  3. Close or rate-limit the offending connection when the handler fires repeatedly; the exception is thrown on the event loop so add metrics/alerts.
  4. Note: throwing inside exceptionHandler propagates up Vert.x — prefer logging + socket.close() instead of rethrowing to avoid killing the event loop.

Example fix

// before (rethrow can disrupt the Vert.x handler pipeline)
parser.exceptionHandler(ex -> {
    throw new RuntimeException("[createDecodeParser][解析异常]", ex);
});

// after (log + close socket, do not rethrow on event loop)
parser.exceptionHandler(ex -> {
    log.error("[createDecodeParser][解析异常]", ex);
    // signal the owning socket to close
});
Defensive patterns

Strategy: try-catch

Validate before calling

// validate the configured delimiter matches observed traffic before relying on the codec
byte[] expected = parseDelimiter(config.getDelimiter());
if (expected.length == 0) {
    throw new IllegalArgumentException("分隔符不能为空");
}

Try / catch

// log + close the offending socket instead of rethrowing on the Vert.x event loop
parser.exceptionHandler(ex -> {
    log.error("[createDecodeParser][解析异常]", ex);
    // signal connection manager to close this socket
});

Prevention

When it happens

Trigger: Device sends a continuous byte stream that never contains the configured delimiter, crossing 64KB; wrong delimiter configured (device terminates with \n but config says \r\n); a malformed/buggy device flooding garbage; delimiter bytes split across TCP segments in a way that never reassembles (rare with Vert.x).

Common situations: Delimiter mismatch between device firmware and gateway config; device firmware forgot to append the delimiter; malicious device; baud-rate/garbage on a serial-to-TCP converter.

Related errors


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