apache/shardingsphere · error · IllegalArgumentException

Expected blr_eoc

Error message

Expected blr_eoc

What it means

SQLFeatureNotSupportedException thrown by updateBlob(String, InputStream, long) on SQL federation ResultSets. This label+stream+length overload is final and throws in AbstractUnsupportedUpdateOperationSQLFederationResultSet like every update method in the class. The design intent is explicit: federation ResultSets expose merged, read-only data, and the entire updatable-ResultSet API surface throws SQLFeatureNotSupportedException naming the operation.

Source

Thrown at database/protocol/dialect/firebird/src/main/java/org/apache/shardingsphere/database/protocol/firebird/packet/command/query/batch/FirebirdParseBatchBlr.java:100

        }
        if (BlrConstants.blr_begin != buffer.readUnsignedByte()) {
            throw new IllegalArgumentException("Expected blr_begin");
        }
        if (BlrConstants.blr_message != buffer.readUnsignedByte()) {
            throw new IllegalArgumentException("Expected blr_message");
        }
        buffer.skipBytes(1);
        FirebirdParseBatchBlr result = parseFormat(buffer);
        validateTermination(buffer, startReaderIndex, blrLength);
        return result;
    }
    
    private static void validateTermination(final ByteBuf buffer, final int startReaderIndex, final int blrLength) {
        if (remainingWithinBlr(buffer, startReaderIndex, blrLength) < 1 || BlrConstants.blr_end != buffer.readUnsignedByte()) {
            throw new IllegalArgumentException("Expected blr_end");
        }
        if (remainingWithinBlr(buffer, startReaderIndex, blrLength) < 1 || BlrConstants.blr_eoc != buffer.readUnsignedByte()) {
            throw new IllegalArgumentException("Expected blr_eoc");
        }
        if (0 != remainingWithinBlr(buffer, startReaderIndex, blrLength)) {
            throw new IllegalArgumentException("Unexpected trailing bytes in BLR");
        }
    }
    
    private static int remainingWithinBlr(final ByteBuf buffer, final int startReaderIndex, final int blrLength) {
        return blrLength - (buffer.readerIndex() - startReaderIndex);
    }
    
    private static void validateSupported(final List<FirebirdBatchColumnDescriptor> fields) {
        for (FirebirdBatchColumnDescriptor each : fields) {
            if (FirebirdBinaryColumnType.BLOB == each.getType()) {
                // TODO Implement BATCH_REGBLOB, BATCH_BLOB_STREAM and BATCH_SET_BPB before accepting BLOB fields.
                throw new FirebirdProtocolException("BLOB fields are not supported in Firebird batch operations");
            }
        }
    }

View on GitHub (pinned to e952770a21)

Solutions

  1. Execute UPDATE ... SET content = ? WHERE ... with ps.setBinaryStream(1, stream, length)
  2. Treat rs.getConcurrency() == CONCUR_READ_ONLY as the signal to use statement-based writes
  3. Adjust the SQL or federation configuration so this query is routed instead of federated

Example fix

// before
rs.updateBlob("content", in, fileSize); // SQLFeatureNotSupportedException

// after
try (PreparedStatement ps = conn.prepareStatement("UPDATE files SET content = ? WHERE id = ?")) {
    ps.setBinaryStream(1, in, fileSize);
    ps.setLong(2, rs.getLong("id"));
    ps.executeUpdate();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (rs.getConcurrency() == ResultSet.CONCUR_READ_ONLY) {
    // label+length stream write unsupported: use UPDATE + setBinaryStream with length
}

Try / catch

try {
    rs.updateBlob("content", inputStream, length);
} catch (SQLFeatureNotSupportedException e) {
    // federation cursor read-only; perform bounded UPDATE DML
}

Prevention

When it happens

Trigger: Calling rs.updateBlob("content", inputStream, length) on a federated ResultSet before rs.updateRow(). Occurs in label-based binary writers that also pass an exact length.

Common situations: Media pipelines that stream known-size assets into columns by name; application onboarding onto ShardingSphere where federation now serves previously simple queries; generic JDBC wrappers that expose all update overloads.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/39eeb0d1e4772028. Report an issue: GitHub.