{"record":{"id":"5e23d9c38aaf53b4","repo":"YunaiV/ruoyi-vue-pro","slug":"createdecodeparser-5e23d9","errorCode":null,"errorMessage":"[createDecodeParser][解析异常]","messagePattern":"\\[createDecodeParser\\]\\[解析异常\\]","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/protocol/tcp/codec/length/IotTcpFixedLengthFrameCodec.java","lineNumber":42,"sourceCode":"     */\n    private final int fixedLength;\n\n    public IotTcpFixedLengthFrameCodec(IotTcpConfig.CodecConfig config) {\n        Assert.notNull(config.getFixedLength(), \"fixedLength 不能为空\");\n        this.fixedLength = config.getFixedLength();\n    }\n\n    @Override\n    public IotTcpCodecTypeEnum getType() {\n        return IotTcpCodecTypeEnum.FIXED_LENGTH;\n    }\n\n    @Override\n    public RecordParser createDecodeParser(Handler<Buffer> handler) {\n        RecordParser parser = RecordParser.newFixed(fixedLength);\n        parser.handler(handler);\n        parser.exceptionHandler(ex -> {\n            throw new RuntimeException(\"[createDecodeParser][解析异常]\", ex);\n        });\n        return parser;\n    }\n\n    @Override\n    public Buffer encode(byte[] data) {\n        // 校验数据长度不能超过固定长度\n        if (data.length > fixedLength) {\n            throw new IllegalArgumentException(String.format(\n                    \"数据长度 %d 超过固定长度 %d\", data.length, fixedLength));\n        }\n        Buffer buffer = Buffer.buffer(fixedLength);\n        buffer.appendBytes(data);\n        // 如果数据不足固定长度，填充 0（RecordParser.newFixed 解码时按固定长度读取，所以发送端需要填充）\n        if (data.length < fixedLength) {\n            byte[] padding = new byte[fixedLength - data.length];\n            buffer.appendBytes(padding);\n        }","sourceCodeStart":24,"sourceCodeEnd":60,"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/protocol/tcp/codec/length/IotTcpFixedLengthFrameCodec.java#L24-L60","documentation":"The Vert.x RecordParser.exceptionHandler for the fixed-length codec rethrows any parser error as RuntimeException. A fixed-length parser rarely errors on its own, so this typically surfaces an underlying Vert.x buffer/state issue or a parser reused incorrectly. The handler wraps whatever Throwable the parser reports.","triggerScenarios":"Vert.x RecordParser internal error; parser invoked after being shared/closed incorrectly; a programmatic misuse triggering an internal IllegalStateException from the parser.","commonSituations":"Codec instance shared across sockets (not thread/connection safe); Vert.x version incompatibility; internal parser state corruption from misuse.","solutions":["Ensure each connection gets its own createDecodeParser() instance (do not cache/share a RecordParser across NetSockets).","Upgrade/align the Vert.x version if a parser bug is suspected (check Vert.x release notes).","Log the cause and close the socket rather than rethrowing on the event loop.","Capture the exact payload that preceded the error to reproduce."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// ensure each connection gets its own parser instance (do not share across sockets)\nRecordParser parser = codec.createDecodeParser(frame -> handleFrame(socket, frame));\nsocket.handler(parser);","typeGuard":null,"tryCatchPattern":"parser.exceptionHandler(ex -> {\n    log.error(\"[createDecodeParser][解析异常]\", ex);\n    socket.close();\n});","preventionTips":["Never share a RecordParser/codec-stateful object across multiple NetSockets.","Keep the Vert.x version aligned across modules.","Log the cause and close the socket rather than rethrowing on the event loop."],"tags":["tcp","codec","vertx","fixed-length"],"backgroundTag":null,"analyzedSha":"0418084e222612af2fc1141f566af454f9236ab1","analyzedAt":"2026-08-14T00:56:18.412Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}