jmoiron/sqlx · error
nil pointer passed to StructScan destination
Error message
nil pointer passed to StructScan destination
What it means
A typed nil pointer (e.g. var u *User; rows.StructScan(u)) passes the Kind()==Ptr check but points at nothing. reflect cannot allocate storage through a nil pointer, so sqlx explicitly rejects nil destinations before attempting the scan.
Source
Thrown at sqlx.go:755
return MapScan(r, dest)
}
func (r *Row) scanAny(dest interface{}, structOnly bool) error {
if r.err != nil {
return r.err
}
if r.rows == nil {
r.err = sql.ErrNoRows
return r.err
}
defer r.rows.Close()
v := reflect.ValueOf(dest)
if v.Kind() != reflect.Ptr {
return errors.New("must pass a pointer, not a value, to StructScan destination")
}
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))
}
View on GitHub (pinned to 41dac167fd)
Solutions
- Allocate before scanning: u := &User{}; rows.StructScan(u)
- Use a value variable and take its address: var u User; rows.StructScan(&u)
- Inside helpers, check reflect.ValueOf(dest).IsNil() and allocate via reflect.New
- Prefer Get/Select which construct destinations for you
Example fix
// before
var u *User
rows.StructScan(u)
// after
u := &User{}
rows.StructScan(u) Defensive patterns
Strategy: validation
Validate before calling
func safeStructScan(rows *sqlx.Rows, dest interface{}) error {
v := reflect.ValueOf(dest)
if v.Kind() != reflect.Ptr || v.IsNil() {
return fmt.Errorf("StructScan needs a non-nil pointer, got %T", dest)
}
return rows.StructScan(dest)
} Type guard
func isNonNilPointer(dest interface{}) bool {
v := reflect.ValueOf(dest)
return v.Kind() == reflect.Ptr && !v.IsNil()
} Try / catch
if err := rows.StructScan(u); err != nil {
if strings.Contains(err.Error(), "nil pointer") {
return fmt.Errorf("allocate destination before scan (u = &User{}): %w", err)
}
return err
} Prevention
- Initialize pointer destinations: dest := &User{} before scanning
- Avoid passing pointer-typed function parameters straight to StructScan without a nil check
- Prefer value variables plus & for scan destinations
When it happens
Trigger: Calling StructScan with a declared-but-uninitialized pointer: var u *User; rows.StructScan(u), or a function parameter of pointer type that the caller left nil.
Common situations: Pointer-typed fields in larger structs left nil; helper functions taking *T parameters called with nil; refactors from value to pointer semantics without allocation.
Related errors
- must pass a pointer, not a value, to StructScan destination
- 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/e3d1e8cca1b81b3d.
Report an issue: GitHub.