googleapis/mcp-toolbox · error

unable to execute query: %w

Error message

unable to execute query: %w

What it means

Returned by the cloud-sql-mssql source's RunSQL when s.MSSQLDB().QueryContext fails to execute the supplied statement. This wraps any driver-level execution error: SQL syntax errors, missing objects, permission denials, timeouts, or dropped connections. The error occurs before any rows are read, so results.Close() is never deferred in this path.

Source

Thrown at internal/sources/cloudsqlmssql/cloud_sql_mssql.go:118

func (s *Source) SourceType() string {
	// Returns Cloud SQL MSSQL source type
	return SourceType
}

func (s *Source) ToConfig() sources.SourceConfig {
	return s.Config
}

func (s *Source) MSSQLDB() *sql.DB {
	// Returns a Cloud SQL MSSQL database connection pool
	return s.Db
}

func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (any, error) {
	results, err := s.MSSQLDB().QueryContext(ctx, statement, params...)
	if err != nil {
		return nil, fmt.Errorf("unable to execute query: %w", err)
	}
	defer results.Close()

	cols, err := results.Columns()
	// 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.
	out := []any{}
	if err == nil && len(cols) > 0 {
		// create an array of values for each column, which can be re-used to scan each row
		rawValues := make([]any, len(cols))
		values := make([]any, len(cols))
		for i := range rawValues {
			values[i] = &rawValues[i]
		}

		for results.Next() {
			scanErr := results.Scan(values...)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Read the wrapped driver error for the exact SQL Server message (line number, error code)
  2. Run the statement manually in SSMS/sqlcmd with the same user to reproduce
  3. Fix SQL syntax or object names in the tool's statement/parameters
  4. Grant the configured user the needed SELECT/EXEC permissions
  5. Increase the request context timeout if the query is long-running

Example fix

// before
SELECT * FORM users WHERE id = @p1;
// after
SELECT * FROM users WHERE id = @p1;
Defensive patterns

Strategy: validation

Validate before calling

// Validate statement non-empty and table names quoted before invoking RunSQL
if strings.TrimSpace(statement) == "" {
    return errors.New("statement must not be empty")
}

Try / catch

results, err := src.RunSQL(ctx, statement, params)
if err != nil {
    if strings.Contains(err.Error(), "unable to execute query") {
        // surface wrapped driver error to the user and let the LLM retry with corrected SQL
        return fmt.Errorf("SQL rejected by SQL Server: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Any tool invocation that reaches Source.RunSQL (e.g. execute-sql tool) with a statement the SQL Server rejects or cannot run: invalid T-SQL syntax, referencing a non-existent table/column, insufficient permissions, parameter count/type mismatch, context deadline exceeded, or connection already closed.

Common situations: LLM-generated SQL with syntax errors, querying tables the configured user lacks SELECT rights on, very long queries hitting a context timeout, stale connections after an instance restart, placeholders (!) param style mismatches with sqlserver driver.

Related errors


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