googleapis/mcp-toolbox · error

unable to execute client: %w

Error message

unable to execute client: %w

What it means

RunSQL (internal/sources/spanner/spanner.go:196) executes statements through spanner client ReadWriteTransaction. The transaction callback collects errors into opErr; if the transaction (including commit/retry attempts) fails, the error is wrapped as "unable to execute client". This is a generic wrapper over any Spanner transaction failure.

Source

Thrown at internal/sources/spanner/spanner.go:196

		stmt.Params = params
	}

	if readOnly {
		iter := s.SpannerClient().Single().Query(ctx, stmt)
		results, opErr = processRows(iter)
	} else {
		_, opErr = s.SpannerClient().ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error {
			iter := txn.Query(ctx, stmt)
			results, err = processRows(iter)
			if err != nil {
				return err
			}
			return nil
		})
	}

	if opErr != nil {
		return nil, fmt.Errorf("unable to execute client: %w", opErr)
	}

	return results, nil
}

func initSpannerClient(ctx context.Context, tracer trace.Tracer, name, project, instance, dbname string) (*spanner.Client, error) {
	//nolint:all // Reassigned ctx
	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, name)
	defer span.End()

	// Configure the connection to the database
	db := fmt.Sprintf("projects/%s/instances/%s/databases/%s", project, instance, dbname)

	// Create spanner client
	userAgent, err := util.UserAgentFromContext(ctx)
	if err != nil {
		return nil, err
	}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Unwrap the %w chain and read the underlying Spanner error code (e.g. googleapi.Error) to identify the real cause
  2. Verify the service account has roles/spanner.databaseUser on the instance
  3. Test the statement directly in the Spanner console to rule out syntax errors
  4. Retry on codes Aborted/Unavailable — the client retries internally but may still exhaust
  5. Check context deadlines if the statement is long-running
Defensive patterns

Strategy: retry

Try / catch

err := source.RunSQL(ctx, stmt, params)
if err != nil {
	var apiErr *googleapi.Error
	if errors.As(err, &apiErr) && (apiErr.Code == 409 || apiErr.Code == 503) {
		// retry with backoff (Aborted/Unavailable)
	}
	return fmt.Errorf("spanner RunSQL failed: %w", err)
}

Prevention

When it happens

Trigger: Running a DML/DDL statement via RunSQL where the transaction fails: Spanner server error, dead aborted transaction exhausted retries, permission denied, statement syntax error, or context cancellation mid-transaction.

Common situations: IAM role lacking spanner.database user privileges; malformed SQL statement; transient aborts during high contention; Spanner instance paused or deleted; network issues between client and Spanner.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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