{"record":{"id":"5152c9320b62d88c","repo":"apache/beam","slug":"failed-to-scan-v","errorCode":null,"errorMessage":"failed to scan %v","messagePattern":"failed to scan (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sdks/go/pkg/beam/io/databaseio/database.go","lineNumber":109,"sourceCode":"\t\treflectRow := reflect.New(f.Type.T)\n\t\trow := reflectRow.Interface() // row : *T\n\t\tif mapper == nil {\n\t\t\tcolumns, err = rows.Columns()\n\t\t\tif err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t\tcolumnsTypes, _ := rows.ColumnTypes()\n\t\t\tif mapper, err = newQueryMapper(columns, columnsTypes, f.Type.T); err != nil {\n\t\t\t\treturn errors.WithContext(err, \"creating rowValues mapper\")\n\t\t\t}\n\t\t}\n\t\trowValues, err := mapper(reflectRow)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\terr = rows.Scan(rowValues...)\n\t\tif err != nil {\n\t\t\treturn errors.Wrapf(err, \"failed to scan %v\", f.Query)\n\t\t}\n\t\tif loader, ok := row.(MapLoader); ok {\n\t\t\tasDereferenceSlice(rowValues)\n\t\t\tloader.LoadMap(asMap(columns, rowValues))\n\t\t} else if loader, ok := row.(SliceLoader); ok {\n\t\t\tasDereferenceSlice(rowValues)\n\t\t\tloader.LoadSlice(rowValues)\n\t\t}\n\t\temit(reflect.ValueOf(row).Elem().Interface()) // emit(*row)\n\t}\n\treturn nil\n}\n\n// Write writes the elements of the given PCollection<T> to database, if columns left empty all table columns are used to insert into, otherwise selected\nfunc Write(s beam.Scope, driver, dsn, table string, columns []string, col beam.PCollection) {\n\tt := col.Type().Type()\n\ts = s.Scope(driver + \".Write\")\n\tpre := beam.AddFixedKey(s, col)","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/go/pkg/beam/io/databaseio/database.go#L91-L127","documentation":"For each row, the DoFn calls rows.Scan(rowValues...) into destination pointers produced by the row mapper. If a column's value cannot be converted into the mapped destination type (NULL into non-nullable field, string into int, wrong column count), it fails with \"failed to scan %v\" wrapping the query text. This is a schema/type mismatch between the SQL result set and the Go element type.","triggerScenarios":"rows.Scan returns an error: destination slice length differs from the column count, NULL scanned into a non-pointer/non-sql.Nullable field, incompatible column value types, or unsupported column types (e.g. arrays, JSON) for the chosen mapper.","commonSituations":"Struct fields not matching SELECT column order/count after editing the query; nullable columns mapped to value types instead of pointers or sql.Null*; driver returning types (e.g. []byte for text) that don't fit the field; SELECT * picking up new columns after migrations.","solutions":["List columns explicitly in the SELECT so column order/count always matches the struct fields.","Change struct fields for nullable columns to pointers or sql.NullString/sql.NullInt64 etc.","Align field types with column types (e.g. scan numeric columns into appropriate int64/float64, decode JSON/text columns manually).","Use a MapLoader/SliceLoader implementation to handle dynamic or wide result sets instead of a fixed struct."],"exampleFix":"// before\ntype user struct {\n  Email string // column is NULLable\n}\n\n// after\ntype user struct {\n  Email sql.NullString // or *string\n}","handlingStrategy":"type-guard","validationCode":"cols, _ := rows.Columns()\nif len(cols) != expectedFieldCount { return fmt.Errorf(\"column count %d != struct fields %d\", len(cols), expectedFieldCount) }","typeGuard":"func isNullableCompatible(field reflect.StructField) bool {\n\tt := field.Type\n\treturn t.Kind() == reflect.Ptr || strings.HasPrefix(t.Name(), \"Null\") // *T or sql.Null*\n}","tryCatchPattern":"if err := rows.Scan(dest...); err != nil {\n\treturn fmt.Errorf(\"failed to scan %q: %w\", query, err) // log columns+row for diagnosis\n}","preventionTips":["Avoid SELECT *; list columns explicitly to keep order/count stable.","Map nullable columns to pointers or sql.Null* types.","Add a test that scans a representative row set into the element struct."],"tags":["database","sql","scan","type-mismatch","go"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}