jmoiron/sqlx · error
scannable dest type %s with >1 columns (%d) in result
Error message
scannable dest type %s with >1 columns (%d) in result
What it means
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.
Source
Thrown at sqlx.go:771
}
if v.IsNil() {
return errors.New("nil pointer passed to StructScan destination")
}
base := reflectx.Deref(v.Type())
scannable := isScannable(base)
if structOnly && scannable {
return structOnlyError(base)
}
columns, err := r.Columns()
if err != nil {
return err
}
if scannable && len(columns) > 1 {
return fmt.Errorf("scannable dest type %s with >1 columns (%d) in result", base.Kind(), len(columns))
}
if scannable {
return r.Scan(dest)
}
m := r.Mapper
fields := m.TraversalsByName(v.Type(), columns)
// if we are not unsafe and are missing fields, return an error
if f, err := missingFields(fields); err != nil && !r.unsafe {
return fmt.Errorf("missing destination name %s in %T", columns[f], dest)
}
values := make([]interface{}, len(columns))
err = fieldsByTraversal(v, fields, values, true)
if err != nil {
return errView on GitHub (pinned to 41dac167fd)
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.
Example fix
// before var names []string db.Select(&names, "SELECT id, name FROM users") // after var names []string db.Select(&names, "SELECT name FROM users")
Defensive patterns
Strategy: validation
Validate before calling
cols, err := rows.Columns()
if err != nil { return err }
if len(cols) != 1 { return fmt.Errorf("need exactly 1 column, got %d", len(cols)) } Type guard
func isScannableSingle(dest interface{}) bool {
t := reflectx.Deref(reflect.TypeOf(dest))
return t.Kind() != reflect.Struct || reflect.PtrTo(t).Implements(_scannerInterface)
} Try / catch
if err := db.Select(&names, q); err != nil {
if strings.Contains(err.Error(), "scannable dest type") {
// fall back to struct destination
}
return err
} Prevention
- Match the SELECT column count to the destination arity.
- Use struct destinations for multi-column results.
- Review queries after edits that add columns.
When it happens
Trigger: rows.ScanScan / ScanInto(dest) where dest's base kind is scannable (primitive or sql.Scanner implementor) and r.Columns() returns len(columns) > 1.
Common situations: 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.
Related errors
- non-struct dest type %s with >1 columns (%d)
- expected %s but got %s
- empty slice passed to 'in' query
- number of bindVars exceeds arguments
- number of bindVars less than number arguments
AI-assisted analysis of jmoiron/sqlx@41dac167fd (2026-09-03).
Data as JSON: /api/errors/94a9d4d23ab490ec.
Report an issue: GitHub.