googleapis/mcp-toolbox · error
unable to parse row: %w
Error message
unable to parse row: %w
What it means
This error is returned when rows.Scan(values...) fails while iterating a result set in RunSQL. It means a row's data could not be converted into the driver's generic any holders — usually due to malformed/unsupported data types (e.g. certain binary, JSON, or temporal encodings), driver protocol corruption, or a connection drop mid-rowset.
Source
Thrown at internal/sources/cloudsqlmysql/cloud_sql_mysql.go:162
}
// 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)
}
out := []any{}
for results.Next() {
err := results.Scan(values...)
if err != nil {
return nil, fmt.Errorf("unable to parse row: %w", err)
}
row := orderedmap.Row{}
for i, name := range cols {
val := rawValues[i]
if val == nil {
row.Add(name, nil)
continue
}
convertedValue, err := mysqlcommon.ConvertToType(colTypes[i], val)
if err != nil {
return nil, fmt.Errorf("errors encountered when converting values: %w", err)
}
row.Add(name, convertedValue)
}
out = append(out, row)
}
View on GitHub (pinned to 8cc6e09de2)
Solutions
- Examine the wrapped driver error; identify the offending column type and cast/convert it in SQL (e.g. CAST(col AS CHAR), TO_JSON for JSON columns).
- Exclude or reshape problematic columns (avoid BLOB/GEOMETRY/BIT in tool outputs; select only needed text/numeric columns).
- Raise max_allowed_packet / timeout settings if the row is being truncated mid-transfer.
- Retry if transient (connection drop); upgrade go-sql-driver/mysql if a type-conversion bug matches.
- Return explicit column lists instead of SELECT * to keep scanned types simple.
Example fix
// before SELECT * FROM shape_data; // after SELECT id, ST_AsText(geom) AS geom_wkt, name FROM shape_data;
Defensive patterns
Strategy: validation
Validate before calling
func validateScannableColumns(cols []string) error {
risky := []string{"blob", "geometry", "point", "polygon", "linestring", "bit", "binary", "varbinary"}
for _, c := range cols {
lc := strings.ToLower(c)
for _, r := range risky {
if strings.Contains(lc, r) {
return fmt.Errorf("column %q may have type %q which can fail generic row scanning; cast it in SQL (e.g. CAST/ST_AsText)", c, r)
}
}
}
return nil
} Type guard
func isScanTypeError(err error) bool {
var mysqlErr *mysql.MySQLError
if errors.As(err, &mysqlErr) {
switch mysqlErr.Number {
case 1301, 1306: // unsupported/truncated data
return true
}
}
msg := strings.ToLower(err.Error())
return strings.Contains(msg, "unsupported scan") ||
strings.Contains(msg, "converting") ||
strings.Contains(msg, "unexpected type")
} Try / catch
result, err := src.RunSQL(ctx, statement, params)
if err != nil {
if strings.Contains(err.Error(), "unable to parse row") && isScanTypeError(err) {
// Rewrite the statement casting exotic columns to text:
// SELECT id, CAST(payload AS CHAR) AS payload FROM t
return nil
}
return err
} Prevention
- Avoid SELECT *; list only text/numeric columns that scan cleanly into generic any holders.
- Cast exotic types in SQL: ST_AsText for geometry, TO_JSON/JSON_UNQUOTE for JSON, CAST(... AS CHAR) for BLOB/BIT.
- Raise max_allowed_packet and net_read_timeout if large rows truncate mid-transfer.
- Keep go-sql-driver/mysql current to pick up scan-conversion fixes.
- Test representative real data (not just schema) against the tool before exposing it to LLMs.
When it happens
Trigger: Calling RunSQL on a result set containing column values the generic scan targets cannot convert (driver-specific unsupported types), a row arriving over a broken connection, or NULL/type mismatch handling tripping the driver's scanner.
Common situations: Selecting unusual column types (BLOB, GEOMETRY, exotic collations, huge DECIMAL/BIT values), truncated packets from oversized rows (net_read_timeout / max_allowed_packet), instance restart mid-iteration, driver version incompatibilities with newer MySQL column types.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- unable to parse row: %w
- unable to create pool: %w
- unable to connect successfully: %w
- unable to execute query: %w
- unable to retrieve rows column name: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/78d30fac5ab91a60.
Report an issue: GitHub.