{"record":{"id":"f826ffbd7f249c8a","repo":"t8y2/dbx","slug":"cannot-start-a-one-shot-transaction-while-a-manual","errorCode":null,"errorMessage":"cannot start a one-shot transaction while a manual transaction is open","messagePattern":"cannot start a one-shot transaction while a manual transaction is open","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agents/drivers/oracle-go/main.go","lineNumber":3704,"sourceCode":"\tif !isOracleIdentifierStart(next) {\n\t\treturn oracleBindParam{}, pos, false\n\t}\n\tend := pos + 2\n\tfor end < len(sqlText) && isOracleIdentifierPart(sqlText[end]) {\n\t\tend++\n\t}\n\treturn oracleBindParam{Name: sqlText[pos+1 : end]}, end, true\n}\n\nfunc restoreOracleCurrentSchema(conn *sql.Conn, schema string) {\n\tctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)\n\tdefer cancel()\n\t_, _ = conn.ExecContext(ctx, \"ALTER SESSION SET CURRENT_SCHEMA = \"+quoteIdentifier(schema))\n}\n\nfunc (s *server) executeTransaction(params map[string]json.RawMessage) (queryResult, error) {\n\tif s.hasManualTransaction() {\n\t\treturn queryResult{}, errors.New(\"cannot start a one-shot transaction while a manual transaction is open\")\n\t}\n\tvar payload struct {\n\t\tStatements []string `json:\"statements\"`\n\t\tSchema     string   `json:\"schema\"`\n\t}\n\tif err := decodeParams(params, &payload); err != nil {\n\t\treturn queryResult{}, err\n\t}\n\tdb, err := s.requireDB()\n\tif err != nil {\n\t\treturn queryResult{}, err\n\t}\n\ttx, err := db.Begin()\n\tif err != nil {\n\t\treturn queryResult{}, err\n\t}\n\tif strings.TrimSpace(payload.Schema) != \"\" {\n\t\tif _, err := tx.Exec(\"ALTER SESSION SET CURRENT_SCHEMA = \" + quoteIdentifier(payload.Schema)); err != nil {","sourceCodeStart":3686,"sourceCodeEnd":3722,"githubUrl":"https://github.com/t8y2/dbx/blob/c0390bff16418b651f4728520d99adf8ce48829a/agents/drivers/oracle-go/main.go#L3686-L3722","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nawait driver.executeTransaction({ statements: [\"INSERT ...\"] }) // errors while manual tx open\n// after\nif (await driver.hasManualTransaction()) {\n  await driver.commitTransaction()\n}\nawait driver.executeTransaction({ statements: [\"INSERT ...\"] })","handlingStrategy":"validation","validationCode":"if (driver.hasManualTransaction()) {\n  throw new Error('end the manual transaction (commit/rollback) before running a one-shot transaction')\n}","typeGuard":"function canRunOneShotTx(d) {\n  return typeof d.hasManualTransaction === 'function' && !d.hasManualTransaction()\n}","tryCatchPattern":"try {\n  await driver.executeTransaction({ statements })\n} catch (e) {\n  if (String(e.message).includes('manual transaction is open')) {\n    await driver.rollbackTransaction()\n    return driver.executeTransaction({ statements }) // retry once\n  }\n  throw e\n}","preventionTips":["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"],"tags":["oracle","transaction","concurrency","state-error"],"backgroundTag":"transaction-already-open","analyzedSha":"c0390bff16418b651f4728520d99adf8ce48829a","analyzedAt":"2026-09-05T23:05:10.900Z","contentChangedAt":"2026-09-05T23:05:10.900Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}