apache/shardingsphere · error · MCPInvalidRequestException
Statement is not a transaction command.
Error message
Statement is not a transaction command.
What it means
Thrown by MCPJdbcTransactionStatementExecutor.executeSavepointStatement when the transaction-statement router cannot classify the statement as SAVEPOINT, ROLLBACK TO SAVEPOINT, or RELEASE SAVEPOINT. It is an MCPInvalidRequestException: the caller asked the transaction endpoint to run something that is not one of the three recognized savepoint commands.
Source
Thrown at mcp/core/src/main/java/org/apache/shardingsphere/mcp/core/tool/handler/execute/MCPJdbcTransactionStatementExecutor.java:84
0, 0, classificationResult.getNormalizedSql());
} catch (final IllegalArgumentException ex) {
throw new MCPInvalidRequestException(ex.getMessage(), ex);
} catch (final IllegalStateException ex) {
throw new MCPTransactionStateException(ex.getMessage(), ex);
}
}
private void executeSavepointStatement(final String sessionId, final MCPDatabaseCapability databaseCapability, final ClassificationResult classificationResult) {
String statementType = classificationResult.getStatementType();
String savepointName = classificationResult.getSavepointName().orElse("");
if ("SAVEPOINT".equals(statementType)) {
executeSavepoint(sessionId, databaseCapability, getRequiredSavepointName(savepointName));
} else if ("ROLLBACK TO SAVEPOINT".equals(statementType)) {
executeRollbackSavepoint(sessionId, databaseCapability, getRequiredSavepointName(savepointName));
} else if ("RELEASE SAVEPOINT".equals(statementType)) {
executeReleaseSavepoint(sessionId, databaseCapability, getRequiredSavepointName(savepointName));
} else {
throw new MCPInvalidRequestException("Statement is not a transaction command.");
}
}
private String getRequiredSavepointName(final String savepointName) {
String result = savepointName.trim();
ShardingSpherePreconditions.checkNotEmpty(result, () -> new IllegalArgumentException("Savepoint name is required."));
return result;
}
private void executeBeginTransaction(final String sessionId, final String databaseName, final MCPDatabaseCapability databaseCapability) {
ShardingSpherePreconditions.checkState(databaseCapability.supportsTransactionControl(), () -> new MCPUnsupportedException("Transaction control is not supported."));
sessionManager.getTransactionResourceManager().beginTransaction(sessionId, databaseName);
}
private void executeCommit(final String sessionId, final MCPDatabaseCapability databaseCapability) {
ShardingSpherePreconditions.checkState(databaseCapability.supportsTransactionControl(), () -> new MCPUnsupportedException("Transaction control is not supported."));
sessionManager.getTransactionResourceManager().commitTransaction(sessionId);
}View on GitHub (pinned to e952770a21)
Solutions
- Use the full canonical forms: `SAVEPOINT name`, `ROLLBACK TO SAVEPOINT name`, `RELEASE SAVEPOINT name`
- Verify you are calling the transaction tool with classified transaction statements, not raw arbitrary SQL
- If the failure persists with canonical SQL, check that the classifier produced the expected statementType and report the mismatch against MCPJdbcTransactionStatementExecutor
Example fix
-- before ROLLBACK TO sp1; RELEASE sp1; -- after ROLLBACK TO SAVEPOINT sp1; RELEASE SAVEPOINT sp1;
Defensive patterns
Strategy: validation
Validate before calling
// Only submit canonical savepoint forms to the transaction tool
private static final Set<String> CANONICAL = Set.of("SAVEPOINT", "ROLLBACK TO SAVEPOINT", "RELEASE SAVEPOINT");
if (!CANONICAL.contains(classify(sql))) throw new IllegalArgumentException("Not a supported transaction command: " + sql); Try / catch
try {
transactionTool.execute(sessionId, sql);
} catch (MCPInvalidRequestException e) {
if (e.getMessage().contains("not a transaction command")) {
// send through the normal execute tool instead if it is plain SQL
}
} Prevention
- Always write SAVEPOINT commands in full canonical form
- Do not send arbitrary SQL to the transaction endpoint
When it happens
Trigger: executeSavepointStatement() is entered with a classificationResult whose statementType is none of "SAVEPOINT", "ROLLBACK TO SAVEPOINT", "RELEASE SAVEPOINT" — typically a classifier mismatch, e.g. `RELEASE sp1` without the SAVEPOINT keyword, `ROLLBACK TO sp1`, or a custom statement type string passed directly to the transaction tool.
Common situations: Dialect differences: PostgreSQL allows `RELEASE SAVEPOINT sp` and MySQL uses `RELEASE SAVEPOINT` only, so scripts written for one engine send short forms the classifier does not produce; calling the transaction MCP tool with free-text SQL instead of going through SQL classification; version changes that rename statement types.
Related errors
- object_types must be an array.
- object_types cannot contain blank values.
- Unsupported object_types value `%s`.
- %s must be an integer between %d and %d.
- Only named savepoint are supported.
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/009407087d2ab8f6.
Report an issue: GitHub.