googleapis/mcp-toolbox · error

unable to iterate through query results: %w

Error message

unable to iterate through query results: %w

What it means

This error wraps any failure returned by the BigQuery row iterator's Next() call while paging through a query's result rows. The library throws it because a successful query job can still fail during row streaming — the initial job completion does not guarantee every page of rows can be fetched. The original iterator error (including context.DeadlineExceeded, transport failures, or page-level BigQuery API errors) is preserved via %w so callers can inspect it with errors.Is/errors.As.

Source

Thrown at internal/sources/bigquery/bigquery.go:643

	// column names to values, and return the collection of rows.
	job, err := query.Run(ctx)
	if err != nil {
		return nil, fmt.Errorf("unable to execute query: %w", err)
	}
	it, err := job.Read(ctx)
	if err != nil {
		return nil, fmt.Errorf("unable to read query results: %w", err)
	}

	out := []any{}
	for s.MaxQueryResultRows <= 0 || len(out) < s.MaxQueryResultRows {
		var val []bigqueryapi.Value
		err = it.Next(&val)
		if err == iterator.Done {
			break
		}
		if err != nil {
			return nil, fmt.Errorf("unable to iterate through query results: %w", err)
		}
		schema := it.Schema
		row := orderedmap.Row{}
		for i, field := range schema {
			row.Add(field.Name, NormalizeValue(val[i]))
		}
		out = append(out, row)
	}
	// If the query returned any rows, return them directly.
	if len(out) > 0 {
		return out, nil
	}

	// This handles the standard case for a SELECT query that successfully
	// executes but returns zero rows.
	if statementType == "SELECT" {
		return "The query returned 0 rows.", nil
	}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Retry the operation (the query itself, not just the iteration) if the wrapped error is transient (net errors, 5xx, 429) — BigQuery iterators are not resumable mid-stream.
  2. Increase the request's context deadline / timeout so slow result streams can complete.
  3. Check the wrapped error with errors.As to see if it's a googleapi.Error and inspect its code for quota or permission issues.
  4. Reduce result size (LIMIT, paging) to shorten the streaming window and lower the chance of mid-iteration failures.

Example fix

// before
for {
  var val []bigqueryapi.Value
  err = it.Next(&val)
  if err == iterator.Done { break }
  if err != nil { return nil, fmt.Errorf("unable to iterate through query results: %w", err) }
}
// after
for {
  var val []bigqueryapi.Value
  ctx, cancel := context.WithTimeout(ctx, 5*time.Minute)
  defer cancel()
  itPager.PageInfo().MaxSize = 10000 // fetch larger pages, fewer round-trips
  err = it.Next(&val)
  if errors.Is(err, iterator.Done) { break }
  if err != nil {
    if isRetryable(err) { /* retry query */ }
    return nil, fmt.Errorf("unable to iterate through query results: %w", err)
  }
}
Defensive patterns

Strategy: try-catch

Try / catch

// Go
rows, err := tool.Invoke(ctx, params)
if err != nil {
  if strings.Contains(err.Error(), "unable to iterate through query results") {
    var gerr *googleapi.Error
    if errors.As(err, &gerr) && (gerr.Code == 429 || gerr.Code >= 500) {
      // retry the whole query after backoff; iterators are not resumable
    }
    if errors.Is(err, context.DeadlineExceeded) {
      // re-invoke with a longer deadline
    }
  }
}

Prevention

When it happens

Trigger: Calling Invoke on a BigQuery tool whose query returns rows, and it.Next(&val) (bigquery.RowIterator.Next) returns a non-nil error other than iterator.Done — e.g. a transient HTTP/transport failure while fetching the next page, a context deadline exceeded mid-iteration, or a page-level BigQuery API error (5xx, rate limit) while reading results.

Common situations: Long-running queries streamed over a slow network; context timeouts during result pagination; BigQuery backend transient errors or 429 rate-limit responses on the tabledata/list pages; stopped or expired jobs; cancelled requests when the caller's context times out.

Related errors


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