{"record":{"id":"2858ffc9e111737e","repo":"jmoiron/sqlx","slug":"non-struct-dest-type-s-with-1-columns-d","errorCode":null,"errorMessage":"non-struct dest type %s with >1 columns (%d)","messagePattern":"non-struct dest type (.+?) with >1 columns \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sqlx.go","lineNumber":934,"sourceCode":"\t}\n\tdirect.SetLen(0)\n\n\tisPtr := slice.Elem().Kind() == reflect.Ptr\n\tbase := reflectx.Deref(slice.Elem())\n\tscannable := isScannable(base)\n\n\tif structOnly && scannable {\n\t\treturn structOnlyError(base)\n\t}\n\n\tcolumns, err := rows.Columns()\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// if it's a base type make sure it only has 1 column;  if not return an error\n\tif scannable && len(columns) > 1 {\n\t\treturn fmt.Errorf(\"non-struct dest type %s with >1 columns (%d)\", base.Kind(), len(columns))\n\t}\n\n\tif !scannable {\n\t\tvar values []interface{}\n\t\tvar m *reflectx.Mapper\n\n\t\tswitch rows := rows.(type) {\n\t\tcase *Rows:\n\t\t\tm = rows.Mapper\n\t\tdefault:\n\t\t\tm = mapper()\n\t\t}\n\n\t\tfields := m.TraversalsByName(base, columns)\n\t\t// if we are not unsafe and are missing fields, return an error\n\t\tif f, err := missingFields(fields); err != nil && !isUnsafe(rows) {\n\t\t\treturn fmt.Errorf(\"missing destination name %s in %T\", columns[f], dest)\n\t\t}","sourceCodeStart":916,"sourceCodeEnd":952,"githubUrl":"https://github.com/jmoiron/sqlx/blob/41dac167fdad5e3fd81d66cafba0951dc6823a30/sqlx.go#L916-L952","documentation":"In scanAll's row-preparation path, if the destination's base type is scannable (primitive or sql.Scanner) but the result set has more than one column, sqlx cannot map several columns onto one value and errors with the destination kind and column count.","triggerScenarios":"Get/Select (scanAll) with a non-struct dest (e.g. []string, *int) while the query returns len(columns) > 1.","commonSituations":"Selecting extra columns (id plus value) into a slice of primitives; leftover SELECT * statements paired with scalar destinations.","solutions":["Restrict the SELECT list to a single column.","Change the destination to a slice of structs and use StructScan semantics.","Alias/restructure the query so only the needed value is returned."],"exampleFix":"// before\nvar ids []int\ndb.Select(&ids, \"SELECT id, name FROM users\")\n\n// after\nvar ids []int\ndb.Select(&ids, \"SELECT id FROM users\")","handlingStrategy":"validation","validationCode":"cols, err := q.Columns()\nif err != nil { return err }\nif isScannable(dest) && len(cols) > 1 {\n    return fmt.Errorf(\"scalar dest needs 1 column, query returns %d\", len(cols))\n}","typeGuard":"func singleColumnOK(dest interface{}, cols []string) bool {\n    t := reflectx.Deref(reflect.TypeOf(dest))\n    isStruct := t.Kind() == reflect.Struct && !reflect.PtrTo(t).Implements(reflect.TypeOf((*sql.Scanner)(nil)).Elem())\n    return isStruct || len(cols) == 1\n}","tryCatchPattern":"if err := db.Select(&vals, q); err != nil {\n    if strings.Contains(err.Error(), \"non-struct dest type\") {\n        return fmt.Errorf(\"query must return one column for %T: %w\", vals, err)\n    }\n    return err\n}","preventionTips":["Keep scalar-destination queries to one selected column.","Prefer struct slices for multi-column results.","Assert column counts in query integration tests."],"tags":["sqlx","select","column-count","scan"],"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"}