googleapis/mcp-toolbox · error

failed to execute ScyllaDB query: %w

Error message

failed to execute ScyllaDB query: %w

What it means

RunSQL executes a CQL query and iterates the result scanner. When the iterator is closed, iter.Close() returns any deferred error encountered while paging rows (driver-level or cluster-level errors); the toolbox wraps it as 'failed to execute ScyllaDB query'. This means the query started but failed partway through fetching results.

Source

Thrown at internal/sources/scylladb/scylladb.go:129

func (s *Source) RunSQL(ctx context.Context, statement string, params parameters.ParamValues) (any, error) {
	sliceParams := params.AsSlice()
	iter := s.ScyllaDBSession().Query(statement, sliceParams...).WithContext(ctx).Iter()

	// Create a slice to store the output
	var out []map[string]interface{}

	// Scan results into a map and append to the slice
	for {
		row := make(map[string]interface{}) // Create a new map for each row
		if !iter.MapScan(row) {
			break // No more rows
		}
		out = append(out, row)
	}

	if err := iter.Close(); err != nil {
		return nil, fmt.Errorf("failed to execute ScyllaDB query: %w", err)
	}
	return out, nil
}

var _ sources.Source = &Source{}

func initScyllaDBSession(ctx context.Context, tracer trace.Tracer, c Config) (*gocql.Session, error) {
	//nolint:all // Reassigned ctx
	ctx, span := sources.InitConnectionSpan(ctx, tracer, SourceType, c.Name)
	defer span.End()

	// Validate authentication configuration
	if c.Password != "" && c.Username == "" {
		return nil, fmt.Errorf("invalid ScyllaDB configuration: password provided without a username")
	}

	cluster := gocql.NewCluster(c.Hosts...)
	cluster.ProtoVersion = c.ProtoVersion

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the wrapped error: ReadTimeout/WriteTimeout → tune `timeout` in the source config or narrow the query with WHERE/LIMIT.
  2. If a node died mid-query, retry the query; consider lowering `pageSize` to reduce per-page latency.
  3. Check statement-level consistency; lower ONE/LOCAL_ONE if consistency failures occur during topology changes.
  4. Add keys/indexes to avoid full-table scans with huge tombstones.
  5. Verify cluster health (`nodetool status`) and retry transient failures with backoff.

Example fix

// before (client)
rows, err := tool.Invoke(ctx, {"sql": "SELECT * FROM events"})
// after — narrow the query and page
rows, err := tool.Invoke(ctx, {"sql": "SELECT * FROM events WHERE day = '2026-09-04' LIMIT 1000"})
Defensive patterns

Strategy: retry

Validate before calling

// Avoid unbounded scans that fail mid-iteration
// Validate the query has a LIMIT or partition-key WHERE clause before invoking
if (!/\bLIMIT\b/i.test(sql) && !/\bWHERE\b/i.test(sql)) {
  throw new Error('query must include LIMIT or a WHERE clause');
}

Try / catch

try {
  const rows = await invokeTool('scylladb_run_sql', { sql });
} catch (e) {
  if (/timeout|unavailable|Stream/i.test(e.message)) {
    await sleep(1000); // retry once with backoff; consider narrower query
    return invokeTool('scylladb_run_sql', { sql });
  }
  throw e;
}

Prevention

When it happens

Trigger: A SELECT/executed via session.Query(...).Iter() begins returning rows, then a paging error occurs: node down mid-iteration, coordinator timeout, consistency not achieved, or the connection dropped. iter.Close() surfaces that error and RunSQL wraps it.

Common situations: Large result sets spanning multiple pages hitting node failures/timeouts; query timeouts on big scans; node restarts during iteration; tombstone-heavy scans triggering ReadTimeout; TLS/connection drops.

Related errors


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