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

  1. Allocate before scanning: u := &User{}; rows.StructScan(u)
  2. Use a value variable and take its address: var u User; rows.StructScan(&u)
  3. Inside helpers, check reflect.ValueOf(dest).IsNil() and allocate via reflect.New
  4. 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

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


AI-assisted analysis of jmoiron/sqlx@41dac167fd (2026-09-03). Data as JSON: /api/errors/e3d1e8cca1b81b3d. Report an issue: GitHub.