{"record":{"id":"f3a3dacb10d071e2","repo":"apache/shardingsphere","slug":"unsupported-blr-version-s","errorCode":null,"errorMessage":"Unsupported BLR version: %s","messagePattern":"Unsupported BLR version: (.+?)","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/batch/FirebirdParseBatchBlr.java","lineNumber":81,"sourceCode":"     *\n     * <p>Used by the packet codec to split a coalesced {@code BATCH_CREATE + BATCH_MSG} frame. Semantically unsupported\n     * but structurally valid fields (such as BLOB) are returned as descriptors instead of being rejected here, so that the\n     * rejection happens later on the command/error path rather than as a codec-level channel close.</p>\n     *\n     * @param blr BLR buffer\n     * @param blrLength BLR length\n     * @return parsed message format\n     * @throws IllegalArgumentException when BLR format is structurally invalid\n     */\n    public static FirebirdParseBatchBlr parseForFraming(final ByteBuf blr, final int blrLength) {\n        if (blrLength < HEADER_LENGTH) {\n            throw new IllegalArgumentException(\"BLR is too short: \" + blrLength);\n        }\n        ByteBuf buffer = blr.duplicate();\n        final int startReaderIndex = buffer.readerIndex();\n        int version = buffer.readUnsignedByte();\n        if (BlrConstants.blr_version4 != version && BlrConstants.blr_version5 != version) {\n            throw new IllegalArgumentException(\"Unsupported BLR version: \" + version);\n        }\n        if (BlrConstants.blr_begin != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_begin\");\n        }\n        if (BlrConstants.blr_message != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_message\");\n        }\n        buffer.skipBytes(1);\n        FirebirdParseBatchBlr result = parseFormat(buffer);\n        validateTermination(buffer, startReaderIndex, blrLength);\n        return result;\n    }\n    \n    private static void validateTermination(final ByteBuf buffer, final int startReaderIndex, final int blrLength) {\n        if (remainingWithinBlr(buffer, startReaderIndex, blrLength) < 1 || BlrConstants.blr_end != buffer.readUnsignedByte()) {\n            throw new IllegalArgumentException(\"Expected blr_end\");\n        }\n        if (remainingWithinBlr(buffer, startReaderIndex, blrLength) < 1 || BlrConstants.blr_eoc != buffer.readUnsignedByte()) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/apache/shardingsphere/blob/e952770a215630a3659c75d64369168cd3e26b82/database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/batch/FirebirdParseBatchBlr.java#L63-L99","documentation":"SQLFeatureNotSupportedException thrown by updateBlob(String, Blob) on SQL federation ResultSets. The column-label variant of updateBlob is final and throws in AbstractUnsupportedUpdateOperationSQLFederationResultSet just like the index variant. SQL federation merges shard results into a read-only cursor, so attaching a Blob to a named column of the current row is categorically unsupported.","triggerScenarios":"Calling rs.updateBlob(\"content\", blob) on a federated ResultSet then rs.updateRow(). Common in label-based persistence helpers handling binary attachments.","commonSituations":"Document-management code updating BLOB columns in place; apps previously running on drivers with CONCUR_UPDATABLE support moved behind ShardingSphere; federation newly triggered by a cross-shard JOIN in a previously simple query.","solutions":["Replace with an UPDATE statement using setBlob or setBinaryStream on PreparedStatement","Branch on rs.getConcurrency() before update attempts; CONCUR_READ_ONLY means statement-based DML only","Avoid federation for binary-write workloads by adjusting query or federation configuration"],"exampleFix":"// before\nrs.updateBlob(\"content\", blob); // SQLFeatureNotSupportedException\n\n// after\ntry (PreparedStatement ps = conn.prepareStatement(\"UPDATE files SET content = ? WHERE id = ?\")) {\n    ps.setBlob(1, blob);\n    ps.setLong(2, rs.getLong(\"id\"));\n    ps.executeUpdate();\n}","handlingStrategy":"try-catch","validationCode":"if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {\n    // label-based updateBlob unsupported: use UPDATE + setBlob\n}","typeGuard":null,"tryCatchPattern":"try {\n    rs.updateBlob(\"content\", blob);\n} catch (SQLFeatureNotSupportedException e) {\n    // fall back to UPDATE DML keyed by primary key\n}","preventionTips":["Refactor attachment uploads to DML writes","Audit binary-write paths when adopting ShardingSphere","Keep editable result sets out of federated queries"],"tags":["jdbc","resultset","sql-federation","read-only","blob"],"backgroundTag":null,"analyzedSha":"e952770a215630a3659c75d64369168cd3e26b82","analyzedAt":"2026-08-14T13:54:53.392Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}