t8y2/dbx · error

begin manual transaction: %w

Error message

begin manual transaction: %w

What it means

After successfully reserving an exclusive connection, the driver starts the actual database transaction with conn.BeginTx. If Oracle rejects the begin (connection already broken, session terminated, driver error), the reserved connection is closed and this wrapped error is returned. The manual transaction is therefore not started.

Source

Thrown at agents/drivers/oracle-go/main.go:1204

	if err != nil {
		return err
	}
	// Hold one exclusive physical connection so DML/SELECT/schema stay on the
	// same Oracle session for the life of the interactive transaction.
	conn, err := db.Conn(context.Background())
	if err != nil {
		return fmt.Errorf("reserve connection for manual transaction: %w", err)
	}
	if strings.TrimSpace(schema) != "" {
		if _, err := conn.ExecContext(context.Background(), "ALTER SESSION SET CURRENT_SCHEMA = "+quoteIdentifier(schema)); err != nil {
			_ = conn.Close()
			return err
		}
	}
	tx, err := conn.BeginTx(context.Background(), nil)
	if err != nil {
		_ = conn.Close()
		return fmt.Errorf("begin manual transaction: %w", err)
	}
	s.manualConn = conn
	s.manualTx = tx
	return nil
}

func (s *server) commitManualTransaction() error {
	if s.manualTx == nil {
		return errors.New("no manual transaction open")
	}
	err := s.manualTx.Commit()
	s.clearManualTransaction()
	return err
}

func (s *server) rollbackManualTransaction() error {
	if s.manualTx == nil {
		return errors.New("no manual transaction open")

View on GitHub (pinned to c0390bff16)

Solutions

  1. Retry the whole beginManualTransaction operation (pool will hand out a fresh connection)
  2. Check for ORA- errors in the wrapped cause (e.g. ORA-00028 session killed, ORA-03113 end-of-file) and address per Oracle docs
  3. Enable connection lifetime/max-idle tuning so stale connections are culled before reuse
  4. Verify network stability between the driver host and the Oracle instance

Example fix

// before
tx, err := conn.BeginTx(ctx, nil) // stale conn -> ORA-03113
// after
for attempt := 0; attempt < 2; attempt++ {
    if err := beginManualTransaction(s, schema); err == nil { break }
    time.Sleep(500 * time.Millisecond) // retry gets a fresh pooled conn
}
Defensive patterns

Strategy: retry

Validate before calling

if err := db.PingContext(ctx); err != nil { return err } // ensure pool conns are healthy before reserve+begin

Try / catch

err := beginManualTransaction(s, schema)
if err != nil && strings.Contains(err.Error(), "begin manual transaction") {
    time.Sleep(250 * time.Millisecond)
    err = beginManualTransaction(s, schema) // retry gets a fresh pooled conn
}

Prevention

When it happens

Trigger: Calling beginManualTransaction when the reserved connection was invalidated between db.Conn and BeginTx (network drop, server killed the session, idle timeout, driver.ErrBadConn), or an Oracle-side error preventing a new transaction on that session.

Common situations: Oracle session killed by a DBA or resource limit while the code runs; firewall/NAT dropping idle connections; begin called immediately after a reconnect where the pooled conn was stale.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/32d63d8f38cb0809. Report an issue: GitHub.