googleapis/mcp-toolbox · error

query execution error: %w

Error message

query execution error: %w

What it means

This error wraps a failure surfaced by database/sql's rows.Err() after rows.ColumnTypes() failed in the Oracle RunSQL read path. ColumnTypes() fails when the driver cannot describe the result set, which usually means the query failed during execution or the result set was already consumed/errored. The code first checks rows.Err() to distinguish a real query error from an empty/undescribable result; only a non-nil rows.Err() becomes this error.

Source

Thrown at internal/sources/oracle/oracle.go:177

			"rows_affected": rowsAffected,
		}, nil
	}
	rows, err := s.OracleDB().QueryContext(ctx, statement, params...)
	if err != nil {
		return nil, fmt.Errorf("unable to execute query: %w", err)
	}
	defer rows.Close()

	// If Columns() errors, it might be a DDL/DML without an OUTPUT clause.
	// We proceed, and results.Err() will catch actual query execution errors.
	// 'out' will remain an empty slice if cols is empty or err is not nil here.
	cols, _ := rows.Columns()

	// Get Column types
	colTypes, err := rows.ColumnTypes()
	if err != nil {
		if err := rows.Err(); err != nil {
			return nil, fmt.Errorf("query execution error: %w", err)
		}
		return []any{}, nil
	}

	out := []any{}
	for rows.Next() {
		values := make([]any, len(cols))
		for i, colType := range colTypes {
			switch strings.ToUpper(colType.DatabaseTypeName()) {
			case "NUMBER", "FLOAT", "BINARY_FLOAT", "BINARY_DOUBLE":
				if _, scale, ok := colType.DecimalSize(); ok && scale == 0 {
					// Scale is 0, treat it as an integer.
					values[i] = new(sql.NullInt64)
				} else {
					// Scale is non-zero or unknown, treat
					// it as a float.
					values[i] = new(sql.NullFloat64)
				}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Inspect the wrapped %w cause in the error chain — it contains the driver's ORA- error code; address that root cause directly.
  2. Increase context timeout or adjust query so it completes within the deadline if the cause is context cancellation.
  3. Check network stability and Oracle session/idle timeout settings (SQLNET.EXPIRE_TIME, firewall idle limits) if disconnects recur.
  4. Verify driver health: try the query in SQL*Plus or SQL Developer with the same user to confirm it runs server-side.
  5. If using go-ora, consider UseOCI: true (godror) to rule out driver-specific cursor handling bugs.

Example fix

// before
cols, _ := rows.Columns()
colTypes, err := rows.ColumnTypes()

// after: check rows.Err() first and add a sane timeout
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
rows, err := db.QueryContext(ctx, statement, params...)
if err != nil { return nil, fmt.Errorf("unable to execute query: %w", err) }
Defensive patterns

Strategy: retry

Validate before calling

if err := db.PingContext(ctx); err != nil {
    return fmt.Errorf("oracle connection unhealthy before query: %w", err)
}

Try / catch

out, err := source.RunSQL(ctx, stmt, params, true)
var qeErr *fmt.wrapError
if err != nil && errors.As(err, &qeErr) && isRetryable(err) {
    time.Sleep(backoff)
    out, err = source.RunSQL(ctx, stmt, params, true)
}
if err != nil { return err }

Prevention

When it happens

Trigger: Calling RunSQL with readOnly=true where the query's result set becomes invalid mid-flight: the connection dropped while rows were being described, the query was canceled via context, or the driver failed to report column types because the server aborted the cursor (e.g. ORA-ORA-01722 mid-cursor, session killed, network reset).

Common situations: Long-running queries hitting Oracle session timeouts or firewall idle disconnects; context deadlines canceled while the query executes; TAF/connection failover breaking an open cursor; network instability between the MCP Toolbox server and the database.

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/32c1850c8e280926. Report an issue: GitHub.