{"record":{"id":"984474f51375e019","repo":"apache/shardingsphere","slug":"invalid-message-length-computed-d-from-blr-but-c","errorCode":null,"errorMessage":"invalid message length: computed %d from BLR but client sent %d","messagePattern":"invalid message length: computed (.+?) from BLR but client sent (.+?)","errorType":"exception","errorClass":"InvalidBatchMessageFormatException","httpStatus":null,"severity":"error","filePath":"proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/batch/FirebirdBatchCreateCommandExecutor.java","lineNumber":89,"sourceCode":"    \n    @Override\n    public Collection<DatabasePacket> execute() throws SQLException {\n        int connectionId = connectionSession.getConnectionId();\n        int statementId = packet.getStatementHandle();\n        if (null == connectionSession.getServerPreparedStatementRegistry().getPreparedStatement(statementId)) {\n            throw new InvalidStatementHandleException(statementId);\n        }\n        if (null != FirebirdBatchRegistry.getInstance().getBatchStatement(connectionId, statementId)) {\n            throw new BatchAlreadyOpenedException(statementId);\n        }\n        ByteBuf batchBlr = packet.getBatchBlr();\n        int blrLength = batchBlr.readableBytes();\n        FirebirdParseBatchBlr messageFormat = FirebirdParseBatchBlr.parse(batchBlr, blrLength);\n        if (messageFormat.getFields().isEmpty()) {\n            throw new BatchParametersRequiredException(statementId);\n        }\n        if (packet.getBatchMessageLength() != messageFormat.getMessageLength()) {\n            throw new InvalidBatchMessageFormatException(\n                    String.format(\"invalid message length: computed %d from BLR but client sent %d\", messageFormat.getMessageLength(), packet.getBatchMessageLength()));\n        }\n        ByteBuf batchParametersBuffer = packet.getBatchParametersBuffer();\n        BatchParameters batchParameters = BatchParameters.parse(batchParametersBuffer);\n        FirebirdBatchRegistry.getInstance().registerBatchStatement(connectionId, statementId,\n                new FirebirdBatchStatement(statementId, messageFormat.getFields(), batchParameters.getBufferSize(), batchParameters.isRecordCounts(), batchParameters.isMultiError()));\n        return Collections.singleton(new FirebirdGenericResponsePacket().setHandle(statementId));\n    }\n    \n    @Getter\n    @RequiredArgsConstructor\n    static final class BatchParameters {\n        \n        private final int version;\n        \n        private final long bufferSize;\n        \n        private final boolean recordCounts;","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/batch/FirebirdBatchCreateCommandExecutor.java#L71-L107","documentation":"InvalidBatchMessageFormatException thrown when the message length declared in the CREATE BATCH packet differs from the length computed by the proxy from the batch BLR (FirebirdParseBatchBlr.getMessageLength()). The two must agree byte-for-byte because each subsequent batch MESSAGE payload is sliced using this length.","triggerScenarios":"packet.getBatchMessageLength() != messageFormat.getMessageLength() after parsing batchBlr; caused by a client computing message length with a different BLR than the one it sends, wrong alignment/short/int type widths in the length calculation, or a corrupted packet.","commonSituations":"hand-rolled or ported client code that computes message length including/excluding the null indicator bitmap differently than the server; client and proxy disagreeing on Firebird version-specific BLR encoding (e.g. int64 vs int slots); truncation from a buggy packet builder.","solutions":["Use a maintained Firebird client library (Jaybird 5+) whose batch BLR and message-length computation match the protocol.","When building BLR manually, derive the message length from the exact same field descriptors used to build the BLR, including null indicators (one bit per field) and alignment padding.","Verify against a real Firebird server with the same statement: if the server accepts it, compare the bytes the client sends to what the proxy's FirebirdParseBatchBlr computed."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (SQLException e) {\n    if (e.getMessage().contains(\"invalid message length\")) {\n        // BLR and declared length disagree: recompute length from the BLR you send, then retry\n        throw new IllegalStateException(\"client BLR/message-length bug\", e);\n    }\n    throw e;\n}","preventionTips":["Never hand-compute batch message length; derive it from the same descriptors used to build the BLR.","Use library-provided batch builders (Jaybird) which keep them consistent."],"tags":["firebird","batch","blr","message-format","protocol"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}