{"record":{"id":"94a9d4d23ab490ec","repo":"jmoiron/sqlx","slug":"scannable-dest-type-s-with-1-columns-d-in-res","errorCode":null,"errorMessage":"scannable dest type %s with >1 columns (%d) in result","messagePattern":"scannable dest type (.+?) with >1 columns \\((.+?)\\) in result","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sqlx.go","lineNumber":771,"sourceCode":"\t}\n\tif v.IsNil() {\n\t\treturn errors.New(\"nil pointer passed to StructScan destination\")\n\t}\n\n\tbase := reflectx.Deref(v.Type())\n\tscannable := isScannable(base)\n\n\tif structOnly && scannable {\n\t\treturn structOnlyError(base)\n\t}\n\n\tcolumns, err := r.Columns()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif scannable && len(columns) > 1 {\n\t\treturn fmt.Errorf(\"scannable dest type %s with >1 columns (%d) in result\", base.Kind(), len(columns))\n\t}\n\n\tif scannable {\n\t\treturn r.Scan(dest)\n\t}\n\n\tm := r.Mapper\n\n\tfields := m.TraversalsByName(v.Type(), columns)\n\t// if we are not unsafe and are missing fields, return an error\n\tif f, err := missingFields(fields); err != nil && !r.unsafe {\n\t\treturn fmt.Errorf(\"missing destination name %s in %T\", columns[f], dest)\n\t}\n\tvalues := make([]interface{}, len(columns))\n\n\terr = fieldsByTraversal(v, fields, values, true)\n\tif err != nil {\n\t\treturn err","sourceCodeStart":753,"sourceCodeEnd":789,"githubUrl":"https://github.com/jmoiron/sqlx/blob/41dac167fdad5e3fd81d66cafba0951dc6823a30/sqlx.go#L753-L789","documentation":"When scanning into a non-struct, \"scannable\" destination (a type implementing sql.Scanner or a primitive like string/int), sqlx requires the result set to contain exactly one column. If the query returns more than one column, ScanInto/StructScan cannot sensibly map multiple columns onto a single value, so it errors with the column count.","triggerScenarios":"rows.ScanScan / ScanInto(dest) where dest's base kind is scannable (primitive or sql.Scanner implementor) and r.Columns() returns len(columns) > 1.","commonSituations":"Scanning into a []string or sql.Scanner struct while the query selects two or more columns (e.g. SELECT id, name ...); accidentally leaving SELECT * when the dest is a slice of primitives.","solutions":["Change the query to select exactly one column (e.g. SELECT name FROM ...).","Switch the destination to a struct so multiple columns can be mapped to fields.","Use sqlx.Rows.Columns()/StructScan manually if you truly need multi-column raw scanning."],"exampleFix":"// before\nvar names []string\ndb.Select(&names, \"SELECT id, name FROM users\")\n\n// after\nvar names []string\ndb.Select(&names, \"SELECT name FROM users\")","handlingStrategy":"validation","validationCode":"cols, err := rows.Columns()\nif err != nil { return err }\nif len(cols) != 1 { return fmt.Errorf(\"need exactly 1 column, got %d\", len(cols)) }","typeGuard":"func isScannableSingle(dest interface{}) bool {\n    t := reflectx.Deref(reflect.TypeOf(dest))\n    return t.Kind() != reflect.Struct || reflect.PtrTo(t).Implements(_scannerInterface)\n}","tryCatchPattern":"if err := db.Select(&names, q); err != nil {\n    if strings.Contains(err.Error(), \"scannable dest type\") {\n        // fall back to struct destination\n    }\n    return err\n}","preventionTips":["Match the SELECT column count to the destination arity.","Use struct destinations for multi-column results.","Review queries after edits that add columns."],"tags":["sqlx","scan","column-count","reflect"],"backgroundTag":"scan-dest-column-mismatch","analyzedSha":"41dac167fdad5e3fd81d66cafba0951dc6823a30","analyzedAt":"2026-09-03T06:10:20.382Z","contentChangedAt":"2026-09-03T06:10:20.382Z","schemaVersion":2},"datasetVersion":"2026-09-10T12:17:11.382Z"}