apache/shardingsphere · error · InvalidBatchHandleException
Invalid batch handle: statement handle %d
Error message
Invalid batch handle: statement handle %d
What it means
InvalidBatchHandleException thrown by FirebirdBatchExecuteCommandExecutor when FirebirdBatchRegistry has no batch registered for (connectionId, statementHandle). EXECUTE BATCH only works after a successful CREATE BATCH (and at least implicitly queued messages or an empty completion state) on the same connection.
Source
Thrown at proxy/frontend/dialect/firebird/src/main/java/org/apache/shardingsphere/proxy/frontend/firebird/command/query/batch/FirebirdBatchExecuteCommandExecutor.java:50
import org.apache.shardingsphere.proxy.frontend.firebird.command.query.FirebirdServerPreparedStatement;
import org.apache.shardingsphere.proxy.frontend.firebird.command.query.transaction.FirebirdTransactionIdGenerator;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Collections;
@RequiredArgsConstructor
public final class FirebirdBatchExecuteCommandExecutor implements CommandExecutor {
private final FirebirdBatchExecuteCommandPacket packet;
private final ConnectionSession connectionSession;
@Override
public Collection<DatabasePacket> execute() throws SQLException {
FirebirdBatchStatement batchStatement = FirebirdBatchRegistry.getInstance().getBatchStatement(connectionSession.getConnectionId(), packet.getStatementHandle());
if (null == batchStatement) {
throw new InvalidBatchHandleException(packet.getStatementHandle());
}
validateTransactionHandle();
int messageCount = batchStatement.getParameterValues().size();
if (batchStatement.getParameterValues().isEmpty()) {
batchStatement.reset();
return Collections.singleton(new FirebirdBatchCompletionStateResponse()
.setHandle(packet.getStatementHandle())
.setRecordsCount(messageCount)
.setUpdateCounts(new int[0]));
}
FirebirdServerPreparedStatement preparedStatement = connectionSession.getServerPreparedStatementRegistry().getPreparedStatement(batchStatement.getStatementHandle());
FirebirdBatchedStatementsExecutor executor = new FirebirdBatchedStatementsExecutor(connectionSession, preparedStatement, batchStatement.getParameterValues(), batchStatement.isMultiError());
FirebirdBatchCompletion completion = executor.executeBatch();
batchStatement.reset();
return Collections.singleton(createResponse(completion, batchStatement.isRecordCounts()));
}
private void validateTransactionHandle() {View on GitHub (pinned to e952770a21)
Solutions
- Follow the sequence PREPARE -> CREATE BATCH -> (MESSAGE)+ -> EXECUTE BATCH on one connection, using the handle from CREATE BATCH.
- After any batch error, re-create the batch before retrying, since failure paths may free the batch.
- Pin all batch calls to a single connection (no pool hand-off between create and execute).
Defensive patterns
Strategy: validation
Validate before calling
if (!openBatches.contains(stmtHandle)) throw new IllegalStateException("no open batch for " + stmtHandle);
sendExecuteBatch(stmtHandle); Try / catch
catch (SQLException e) {
if (e.getMessage().contains("Invalid batch handle")) { int h = recreateBatch(sql); sendExecuteBatch(h); } else throw e;
} Prevention
- Track open batch handles client-side and clear them on close/free.
- Re-create the batch after any error before retrying execute.
When it happens
Trigger: execute() looks up FirebirdBatchRegistry.getInstance().getBatchStatement(connectionSession.getConnectionId(), packet.getStatementHandle()); null means CREATE BATCH was never sent, the batch was closed/freed, or the handle belongs to another connection.
Common situations: client calls executeBatch before addBatch/createBatch completed; batch state was torn down by FREE STATEMENT after an error; connection pool switches physical connections between create and execute; client bug desynchronizing handles after re-prepare.
Related errors
- Invalid batch handle: statement handle %d
- Invalid statement handle: %d
- Batch already opened for statement handle %d
- Invalid statement handle: %d
- Statement used in batch must have parameters
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/1f2f6e44b95e40e3.
Report an issue: GitHub.