t8y2/dbx · error
cannot start a one-shot transaction while a manual transacti
Error message
cannot start a one-shot transaction while a manual transaction is open
What it means
executeTransaction runs one-shot, multi-statement transactions and is mutually exclusive with the agent's manual transaction mode. If a manual transaction is currently open (hasManualTransaction() is true), starting a one-shot transaction would mix two independent transaction contexts on the same session, so the agent rejects the request outright.
Source
Thrown at agents/drivers/oracle-go/main.go:3704
if !isOracleIdentifierStart(next) {
return oracleBindParam{}, pos, false
}
end := pos + 2
for end < len(sqlText) && isOracleIdentifierPart(sqlText[end]) {
end++
}
return oracleBindParam{Name: sqlText[pos+1 : end]}, end, true
}
func restoreOracleCurrentSchema(conn *sql.Conn, schema string) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
_, _ = conn.ExecContext(ctx, "ALTER SESSION SET CURRENT_SCHEMA = "+quoteIdentifier(schema))
}
func (s *server) executeTransaction(params map[string]json.RawMessage) (queryResult, error) {
if s.hasManualTransaction() {
return queryResult{}, errors.New("cannot start a one-shot transaction while a manual transaction is open")
}
var payload struct {
Statements []string `json:"statements"`
Schema string `json:"schema"`
}
if err := decodeParams(params, &payload); err != nil {
return queryResult{}, err
}
db, err := s.requireDB()
if err != nil {
return queryResult{}, err
}
tx, err := db.Begin()
if err != nil {
return queryResult{}, err
}
if strings.TrimSpace(payload.Schema) != "" {
if _, err := tx.Exec("ALTER SESSION SET CURRENT_SCHEMA = " + quoteIdentifier(payload.Schema)); err != nil {View on GitHub (pinned to c0390bff16)
Solutions
- Commit or roll back the open manual transaction before calling executeTransaction
- Route one-shot transactions through a different agent/connection than the one holding the manual transaction
- Audit error paths so manual transactions are always ended (deferred commit/rollback)
- Check hasManualTransaction() before issuing executeTransaction and branch accordingly
Example fix
// before
await driver.executeTransaction({ statements: ["INSERT ..."] }) // errors while manual tx open
// after
if (await driver.hasManualTransaction()) {
await driver.commitTransaction()
}
await driver.executeTransaction({ statements: ["INSERT ..."] }) Defensive patterns
Strategy: validation
Validate before calling
if (driver.hasManualTransaction()) {
throw new Error('end the manual transaction (commit/rollback) before running a one-shot transaction')
} Type guard
function canRunOneShotTx(d) {
return typeof d.hasManualTransaction === 'function' && !d.hasManualTransaction()
} Try / catch
try {
await driver.executeTransaction({ statements })
} catch (e) {
if (String(e.message).includes('manual transaction is open')) {
await driver.rollbackTransaction()
return driver.executeTransaction({ statements }) // retry once
}
throw e
} Prevention
- Keep manual transactions and one-shot executeTransaction calls on separate agent connections
- Always end manual transactions with deferred commit/rollback on every exit path
- Add a watchdog that detects manual transactions left open beyond a timeout
- Check hasManualTransaction() before scheduling background one-shot transactions
When it happens
Trigger: Calling the execute-transaction RPC while a 'begin manual transaction' is open (no commit/rollback yet); a background job issuing one-shot transactions while a long-lived manual transaction is held; leaked manual transactions that were never committed or rolled back.
Common situations: An app holding a manual transaction for interactive edits while scheduled jobs fire one-shot transactions through the same agent; an exception path that left a manual transaction open, blocking all subsequent executeTransaction calls; connection-pool sharing across components with different transaction styles.
Related errors
- manual transaction already open
- no manual transaction open
- reserve connection for manual transaction: %w
- begin manual transaction: %w
- JDBC Session was quarantined while waiting for a connection
AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05).
Data as JSON: /api/errors/f826ffbd7f249c8a.
Report an issue: GitHub.