ent/ent · error
sql/scan: unsupported type ([]%s)
Error message
sql/scan: unsupported type ([]%s)
What it means
scanType only supports element types that are directly scannable (primitives, string, []byte, sql.Scanner implementations), pointers to those, or structs. Any other slice element kind (map, chan, func, slice, interface with methods, invalid) is rejected with this message naming the kind.
Source
Thrown at dialect/sql/scan.go:159
return values
}
// scanType returns rowScan for the given reflect.Type.
func scanType(typ reflect.Type, columns []string) (*rowScan, error) {
switch k := typ.Kind(); {
case assignable(typ):
return &rowScan{
columns: []reflect.Type{typ},
value: func(v ...any) (reflect.Value, error) {
return reflect.Indirect(reflect.ValueOf(v[0])), nil
},
}, nil
case k == reflect.Ptr:
return scanPtr(typ, columns)
case k == reflect.Struct:
return scanStruct(typ, columns)
default:
return nil, fmt.Errorf("sql/scan: unsupported type ([]%s)", k)
}
}
var (
timeType = reflect.TypeOf(time.Time{})
scannerType = reflect.TypeOf((*sql.Scanner)(nil)).Elem()
nullJSONType = reflect.TypeOf((*nullJSON)(nil)).Elem()
)
// nullJSON represents a json.RawMessage that may be NULL.
type nullJSON json.RawMessage
// Scan implements the sql.Scanner interface.
func (j *nullJSON) Scan(v interface{}) error {
if v == nil {
return nil
}
*j = v.([]byte)View on GitHub (pinned to 69d5d4deb1)
Solutions
- Scan into a slice of structs (or a sql.Scanner-implementing type) whose fields match the selected columns
- Implement the sql.Scanner interface on the element type
- If dynamic columns are needed, scan into []any / use rows.Scan manually instead of ScanSlice
Example fix
// before
var out []map[string]any
sql.ScanSlice(rows, &out) // unsupported type ([]map)
// after
type Row struct{ ID int; Name string }
var out []Row
sql.ScanSlice(rows, &out) Defensive patterns
Strategy: type-guard
Validate before calling
func scannableElem(t reflect.Type) bool {
switch t.Kind() {
case reflect.Struct, reflect.Ptr:
return true
case reflect.String, reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
return true
}
return reflect.PointerTo(t) != nil && t.Implements(scannerType)
} Type guard
func isScannableSlice(v any) bool {
rv := reflect.ValueOf(v)
return rv.Kind() == reflect.Ptr && rv.Elem().Kind() == reflect.Slice &&
(rv.Elem().Type().Elem().Kind() == reflect.Struct ||
rv.Elem().Type().Elem().Implements(reflect.TypeOf((*sql.Scanner)(nil)).Elem()))
} Prevention
- Never pass []map[string]any or slices of slices to ScanSlice; use structs
- Implement sql.Scanner on custom element types
- Use ent's typed generated structs as scan targets
When it happens
Trigger: Calling ScanSlice with a slice whose element kind is not scannable — e.g. *[]map[string]any, []chan int, [][]int, []func(), or a custom struct-like type that neither implements sql.Scanner nor is a struct.
Common situations: Trying to scan raw rows into []map[string]any (a common expectation from other ORMs); passing a slice of slices for multi-column results; typos where the destination should have been a struct.
Related errors
- sql/scan: columns do not match (%d > %d)
- sql/scan: missing struct field for column: %s (%s)
- cannot unmarshal into a non pointer
- {{ $pkg }}: missing options for {{ $builder }}.OnConflict
- entsql: view query should not contain arguments. got: %d
AI-assisted analysis of ent/ent@69d5d4deb1 (2026-09-03).
Data as JSON: /api/errors/43a16de326a49979.
Report an issue: GitHub.