googleapis/mcp-toolbox · error

unable to parse row: %w

Error message

unable to parse row: %w

What it means

This error occurs in `RunSQL` when `results.Scan(values...)` fails while iterating rows. The source scans each column into a `sql.RawBytes`, so scanning fails if the row shape doesn't match expectations — e.g. driver-level conversion problems or a NULL/encoding edge case the raw-bytes scan cannot handle.

Source

Thrown at internal/sources/mssql/mssql.go:136

	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...)
			if scanErr != nil {
				return nil, fmt.Errorf("unable to parse row: %w", scanErr)
			}
			row := orderedmap.Row{}
			for i, name := range cols {
				row.Add(name, rawValues[i])
			}
			out = append(out, row)
		}
	}

	// Check for errors from iterating over rows or from the query execution itself.
	// results.Close() is handled by defer.
	if err := results.Err(); err != nil {
		return nil, fmt.Errorf("errors encountered during query execution or row processing: %w", err)
	}

	return out, nil
}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Cast problematic columns in SQL (CAST(col AS NVARCHAR(MAX))) to friendly types
  2. Unwrap the error to identify which column/type failed
  3. Upgrade the go-mssqldb driver to the latest version
  4. Avoid SELECT *; select only typed, well-defined columns

Example fix

// before
stmt := "SELECT geo FROM places" // geometry column fails to scan
// after
stmt := "SELECT CAST(geo AS NVARCHAR(MAX)) AS geo FROM places"
Defensive patterns

Strategy: type-guard

Type guard

func isScanErr(err error) bool {
    return err != nil && strings.Contains(err.Error(), "unable to parse row")
}

Try / catch

res, err := src.RunSQL(ctx, stmt, nil)
if err != nil && strings.Contains(err.Error(), "unable to parse row") {
    return fmt.Errorf("column type not scannable; CAST it in SQL: %w", err)
}

Prevention

When it happens

Trigger: Calling RunSQL on a result set where Scan into []sql.RawBytes fails: driver conversion errors for unusual column types, column count changes mid-cursor, or a driver/dialect quirk with certain data types (e.g. some CLR/variant types).

Common situations: Querying columns with exotic types (hierarchyid, geometry, sql_variant) that the driver struggles to expose as raw bytes; schema changed between query and scan; driver version bugs with specific type mappings.

Understand the failure class

Related errors


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