apache/shardingsphere · error · FirebirdProtocolException

Unknown DSQL option type

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.

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.

Appendix: 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)