apache/shardingsphere · error · FirebirdProtocolException

Unknown DSQL option type %d

Error message

Unknown DSQL option type %d

What it means

FirebirdProtocolException thrown by FirebirdFreeStatementCommandExecutor when the option int in a FREE STATEMENT packet is not one of DROP, UNPREPARE, or CLOSE. Unknown option values mean the packet is malformed or the client uses a DSQL free option this proxy does not implement.

Source

Thrown at proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/statement/free/FirebirdFreeStatementCommandExecutor.java:57

    
    private final FirebirdFreeStatementPacket packet;
    
    private final ConnectionSession connectionSession;
    
    @Override
    public Collection<DatabasePacket> execute() throws SQLException {
        switch (packet.getOption()) {
            case FirebirdFreeStatementPacket.DROP:
            case FirebirdFreeStatementPacket.UNPREPARE:
                connectionSession.getServerPreparedStatementRegistry().removePreparedStatement(packet.getStatementId());
                FirebirdBatchRegistry.getInstance().unregisterBatchStatement(connectionSession.getConnectionId(), packet.getStatementId());
                FirebirdStatementResourceCleaner.clean(connectionSession, packet.getStatementId(), true);
                break;
            case FirebirdFreeStatementPacket.CLOSE:
                FirebirdStatementResourceCleaner.clean(connectionSession, packet.getStatementId(), false);
                break;
            default:
                throw new FirebirdProtocolException("Unknown DSQL option type %d", packet.getOption());
        }
        return Collections.singleton(new FirebirdGenericResponsePacket());
    }
}

View on GitHub (pinned to e952770a21)

Solutions

  1. Send only the DROP, UNPREPARE or CLOSE option constants exactly as the Firebird DSQL API defines them.
  2. If the option is a bitmask in your client, mask to the single supported option rather than OR-ing flags.
  3. Verify overall packet layout (option int position) against the Firebird wire protocol when hand-encoding.
Defensive patterns

Strategy: validation

Validate before calling

static final int DSQL_DROP = 2, DSQL_UNPREPARE = 4, DSQL_CLOSE = 1;
if (!Set.of(DSQL_DROP, DSQL_UNPREPARE, DSQL_CLOSE).contains(option)) throw new IllegalArgumentException("bad free option");
sendFreeStatement(stmtHandle, option);

Try / catch

catch (SQLException e) {
    if (e.getMessage().contains("Unknown DSQL option")) { sendFreeStatement(stmtHandle, DSQL_DROP); } else throw e;
}

Prevention

When it happens

Trigger: switch (packet.getOption()) hits default; only FirebirdFreeStatementPacket.DROP, .UNPREPARE (both remove the prepared statement and unregister any batch) and .CLOSE (resource cleanup only) are accepted.

Common situations: hand-written clients sending a raw Firebird DSQL_free option bitmask that includes unhandled bits; newer client sending an option constant added after the proxy implementation; packet misalignment making a different field land in the option slot.

Related errors


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