googleapis/mcp-toolbox · error
unable to parse row: %w
Error message
unable to parse row: %w
What it means
Wraps rows.Scan failures while iterating result rows in RunSQL. Scan fails when a column value cannot be converted into the *interface{} destination — usually a driver-level type (e.g. Firebird BLOB subtype, numeric/decimal, timestamp with unusual precision) the firebirdsql driver returns in a form database/sql rejects.
Source
Thrown at internal/sources/firebird/firebird.go:127
defer rows.Close()
cols, err := rows.Columns()
if err != nil {
return nil, fmt.Errorf("unable to get columns: %w", err)
}
values := make([]any, len(cols))
scanArgs := make([]any, len(values))
for i := range values {
scanArgs[i] = &values[i]
}
out := []any{}
for rows.Next() {
err = rows.Scan(scanArgs...)
if err != nil {
return nil, fmt.Errorf("unable to parse row: %w", err)
}
vMap := make(map[string]any)
for i, col := range cols {
if b, ok := values[i].([]byte); ok {
vMap[col] = string(b)
} else {
vMap[col] = values[i]
}
}
out = append(out, vMap)
}
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("error iterating rows: %w", err)
}
// In most cases, DML/DDL statements like INSERT, UPDATE, CREATE, etc. might return no rowsView on GitHub (pinned to 8cc6e09de2)
Solutions
- Cast problematic columns in SQL (e.g. CAST(blob_col AS VARCHAR(...)) or SUBSTRING) instead of selecting raw BLOB/ARRAY columns
- Upgrade the firebirdsql driver to the latest version for scan fixes
- Set a compatible connection charset (e.g. UTF8) in the DSN
- Narrow the SELECT list to plain scalar columns
Example fix
// before
err = rows.Scan(scanArgs...)
if err != nil {
return nil, fmt.Errorf("unable to parse row: %w", err)
}
// after
err = rows.Scan(scanArgs...)
if err != nil {
return nil, fmt.Errorf("unable to parse row %d: %w", len(out), err)
} Defensive patterns
Strategy: validation
Validate before calling
// Avoid raw BLOB/ARRAY columns in the SELECT list
for _, col := range problematicTypes {
if strings.Contains(strings.ToUpper(statement), col) {
return fmt.Errorf("cast %s to VARCHAR in SQL to avoid scan errors", col)
}
} Type guard
func isScanTypeError(err error) bool {
return strings.Contains(err.Error(), "unsupported Scan") || strings.Contains(err.Error(), "converting")
} Try / catch
err = rows.Scan(scanArgs...)
if err != nil {
if isScanTypeError(err) {
return nil, fmt.Errorf("unsupported column type at row %d; CAST the column in SQL: %w", len(out), err)
}
return nil, fmt.Errorf("unable to parse row %d: %w", len(out), err)
} Prevention
- CAST BLOB/ARRAY/DECIMAL columns to scalar types in SQL
- Set an explicit UTF8-compatible connection charset in the DSN
- Scan with sql.RawBytes or sql.Null* types for nullable/odd columns
- Add a CI query covering the widest-schema table to catch scan regressions
When it happens
Trigger: RunSQL hits a row containing a column type the driver cannot scan into any (e.g. malformed BLOB/ARRAY columns, oversized DECIMAL, NULL handling bug in the driver, or charset decoding failure).
Common situations: SELECT * on tables with BLOB or array columns; Firebird dialect 1 legacy column types; non-UTF8 character-set databases producing undecodable strings; driver version bugs with TIMESTAMP/TIME 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 get columns: %w
AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05).
Data as JSON: /api/errors/01a878f400a63e86.
Report an issue: GitHub.