googleapis/mcp-toolbox · error

unable to execute query: %w

Error message

unable to execute query: %w

What it means

RunSQL wraps any error returned by database/sql QueryContext with this message. It means MySQL rejected or failed to run the SQL statement — including connection failures at query time, syntax errors, unknown tables/columns, permission denials, and context cancellations (timeouts). The statement has sqlcommenter comments prepended before execution.

Source

Thrown at internal/sources/cloudsqlmysql/cloud_sql_mysql.go:137

	if err := s.MySQLPool().QueryRowContext(ctx, "SHOW VARIABLES LIKE 'performance_schema'").Scan(&name, &value); err != nil {
		return false, err
	}
	return value == "ON", nil
}

func (s *Source) RetrieveSourceVersion(ctx context.Context) (string, error) {
	var version string
	if err := s.MySQLPool().QueryRowContext(ctx, "SELECT VERSION()").Scan(&version); err != nil {
		return "", err
	}
	return version, nil
}

func (s *Source) RunSQL(ctx context.Context, statement string, params []any) (any, error) {
	statement = sqlcommenter.PrependComment(ctx, statement, SourceType, s.SQLCommenter)
	results, err := s.MySQLPool().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 err != nil {
		return nil, fmt.Errorf("unable to retrieve rows column name: %w", err)
	}

	// 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]
	}

	colTypes, err := results.ColumnTypes()
	if err != nil {
		return nil, fmt.Errorf("unable to get column types: %w", err)

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Inspect the wrapped MySQL error in the message: fix SQL syntax or identifier names (1054 unknown column, 1146 unknown table, 1064 syntax error).
  2. Grant the configured user the required privileges (e.g. SELECT on the target schema).
  3. Run the statement directly with a mysql client to confirm it is valid against the target database.
  4. If it is a timeout, increase the request/context timeout or optimize the query (add indexes, add LIMIT).
  5. If connections are dropping, check instance max_connections and network idle timeouts.

Example fix

// before
SELECT nam FROM users;
// after
SELECT name FROM users;
Defensive patterns

Strategy: try-catch

Validate before calling

func validateSQL(statement, database string) error {
    s := strings.TrimSpace(statement)
    if s == "" {
        return fmt.Errorf("empty statement")
    }
    lower := strings.ToLower(s)
    if !strings.HasPrefix(lower, "select") && !strings.HasPrefix(lower, "show") &&
        !strings.HasPrefix(lower, "describe") && !strings.HasPrefix(lower, "explain") {
        return fmt.Errorf("only read statements are supported")
    }
    return nil
}

Type guard

func isMySQLErrorCode(err error, codes ...uint16) bool {
    var mysqlErr *mysql.MySQLError
    if errors.As(err, &mysqlErr) {
        for _, c := range codes {
            if mysqlErr.Number == c {
                return true
            }
        }
    }
    return false
}

Try / catch

result, err := src.RunSQL(ctx, statement, params)
if err != nil {
    var mysqlErr *mysql.MySQLError
    switch {
    case errors.As(err, &mysqlErr) && mysqlErr.Number == 1146:
        // unknown table: hint the caller to list tables
    case errors.As(err, &mysqlErr) && mysqlErr.Number == 1064:
        // syntax error: surface mysqlErr.Message back to the LLM to fix SQL
    case errors.Is(err, context.DeadlineExceeded):
        // timeout: retry with a larger deadline or add LIMIT
    }
    return err
}

Prevention

When it happens

Trigger: Calling the execute_sql tool / Source.RunSQL with: syntactically invalid SQL, references to non-existent tables or columns, a user without the needed privileges, an empty result-set read failing at connection level, or the context being canceled while executing.

Common situations: LLM-generated SQL with typos, querying a table that exists in a different database, read-only user lacking SELECT grants, query exceeding a client timeout (context deadline exceeded), server closing idle connections, reserved-word misuse in identifiers.

Related errors


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