jmoiron/sqlx · error
non-struct dest type %s with >1 columns (%d)
Error message
non-struct dest type %s with >1 columns (%d)
What it means
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.
Source
Thrown at sqlx.go:934
}
direct.SetLen(0)
isPtr := slice.Elem().Kind() == reflect.Ptr
base := reflectx.Deref(slice.Elem())
scannable := isScannable(base)
if structOnly && scannable {
return structOnlyError(base)
}
columns, err := rows.Columns()
if err != nil {
return err
}
// if it's a base type make sure it only has 1 column; if not return an error
if scannable && len(columns) > 1 {
return fmt.Errorf("non-struct dest type %s with >1 columns (%d)", base.Kind(), len(columns))
}
if !scannable {
var values []interface{}
var m *reflectx.Mapper
switch rows := rows.(type) {
case *Rows:
m = rows.Mapper
default:
m = mapper()
}
fields := m.TraversalsByName(base, columns)
// if we are not unsafe and are missing fields, return an error
if f, err := missingFields(fields); err != nil && !isUnsafe(rows) {
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
}View on GitHub (pinned to 41dac167fd)
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.
Example fix
// before var ids []int db.Select(&ids, "SELECT id, name FROM users") // after var ids []int db.Select(&ids, "SELECT id FROM users")
Defensive patterns
Strategy: validation
Validate before calling
cols, err := q.Columns()
if err != nil { return err }
if isScannable(dest) && len(cols) > 1 {
return fmt.Errorf("scalar dest needs 1 column, query returns %d", len(cols))
} Type guard
func singleColumnOK(dest interface{}, cols []string) bool {
t := reflectx.Deref(reflect.TypeOf(dest))
isStruct := t.Kind() == reflect.Struct && !reflect.PtrTo(t).Implements(reflect.TypeOf((*sql.Scanner)(nil)).Elem())
return isStruct || len(cols) == 1
} Try / catch
if err := db.Select(&vals, q); err != nil {
if strings.Contains(err.Error(), "non-struct dest type") {
return fmt.Errorf("query must return one column for %T: %w", vals, err)
}
return err
} Prevention
- Keep scalar-destination queries to one selected column.
- Prefer struct slices for multi-column results.
- Assert column counts in query integration tests.
When it happens
Trigger: Get/Select (scanAll) with a non-struct dest (e.g. []string, *int) while the query returns len(columns) > 1.
Common situations: Selecting extra columns (id plus value) into a slice of primitives; leftover SELECT * statements paired with scalar destinations.
Related errors
- scannable dest type %s with >1 columns (%d) in result
- empty slice passed to 'in' query
- number of bindVars exceeds arguments
- number of bindVars less than number arguments
- unexpected `:` while reading named param at
AI-assisted analysis of jmoiron/sqlx@41dac167fd (2026-09-03).
Data as JSON: /api/errors/2858ffc9e111737e.
Report an issue: GitHub.