{"record":{"id":"78d30fac5ab91a60","repo":"googleapis/mcp-toolbox","slug":"unable-to-parse-row-w-78d30f","errorCode":null,"errorMessage":"unable to parse row: %w","messagePattern":"unable to parse row: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/sources/cloudsqlmysql/cloud_sql_mysql.go","lineNumber":162,"sourceCode":"\t}\n\n\t// create an array of values for each column, which can be re-used to scan each row\n\trawValues := make([]any, len(cols))\n\tvalues := make([]any, len(cols))\n\tfor i := range rawValues {\n\t\tvalues[i] = &rawValues[i]\n\t}\n\n\tcolTypes, err := results.ColumnTypes()\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to get column types: %w\", err)\n\t}\n\n\tout := []any{}\n\tfor results.Next() {\n\t\terr := results.Scan(values...)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unable to parse row: %w\", err)\n\t\t}\n\t\trow := orderedmap.Row{}\n\t\tfor i, name := range cols {\n\t\t\tval := rawValues[i]\n\t\t\tif val == nil {\n\t\t\t\trow.Add(name, nil)\n\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tconvertedValue, err := mysqlcommon.ConvertToType(colTypes[i], val)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"errors encountered when converting values: %w\", err)\n\t\t\t}\n\t\t\trow.Add(name, convertedValue)\n\t\t}\n\t\tout = append(out, row)\n\t}\n","sourceCodeStart":144,"sourceCodeEnd":180,"githubUrl":"https://github.com/googleapis/mcp-toolbox/blob/8cc6e09de2ad7b8bffc77751799585a1401a48eb/internal/sources/cloudsqlmysql/cloud_sql_mysql.go#L144-L180","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nSELECT * FROM shape_data;\n// after\nSELECT id, ST_AsText(geom) AS geom_wkt, name FROM shape_data;","handlingStrategy":"validation","validationCode":"func validateScannableColumns(cols []string) error {\n    risky := []string{\"blob\", \"geometry\", \"point\", \"polygon\", \"linestring\", \"bit\", \"binary\", \"varbinary\"}\n    for _, c := range cols {\n        lc := strings.ToLower(c)\n        for _, r := range risky {\n            if strings.Contains(lc, r) {\n                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)\n            }\n        }\n    }\n    return nil\n}","typeGuard":"func isScanTypeError(err error) bool {\n    var mysqlErr *mysql.MySQLError\n    if errors.As(err, &mysqlErr) {\n        switch mysqlErr.Number {\n        case 1301, 1306: // unsupported/truncated data\n            return true\n        }\n    }\n    msg := strings.ToLower(err.Error())\n    return strings.Contains(msg, \"unsupported scan\") ||\n        strings.Contains(msg, \"converting\") ||\n        strings.Contains(msg, \"unexpected type\")\n}","tryCatchPattern":"result, err := src.RunSQL(ctx, statement, params)\nif err != nil {\n    if strings.Contains(err.Error(), \"unable to parse row\") && isScanTypeError(err) {\n        // Rewrite the statement casting exotic columns to text:\n        // SELECT id, CAST(payload AS CHAR) AS payload FROM t\n        return nil\n    }\n    return err\n}","preventionTips":["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."],"tags":["mysql","row-scan","type-conversion","cloudsql"],"backgroundTag":"sql-row-scan-failed","analyzedSha":"8cc6e09de2ad7b8bffc77751799585a1401a48eb","analyzedAt":"2026-09-05T01:10:36.887Z","contentChangedAt":"2026-09-05T01:10:36.887Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}