AlistGo/alist · error
cannot scan %T
Error message
cannot scan %T
What it means
Returned by (*Paths).Scan, the GORM/driver Valuer-Scanner hook for the Paths type (a []string stored as JSON). It fires when the database driver hands back a column value whose Go type is neither []byte, string, nor nil — i.e. the column cannot be deserialized into the JSON string array.
Source
Thrown at internal/model/paths.go:25
)
type Paths []string
func (p Paths) Value() (driver.Value, error) {
return json.Marshal([]string(p))
}
func (p *Paths) Scan(value interface{}) error {
switch v := value.(type) {
case []byte:
return json.Unmarshal(v, (*[]string)(p))
case string:
return json.Unmarshal([]byte(v), (*[]string)(p))
case nil:
*p = nil
return nil
default:
return fmt.Errorf("cannot scan %T", value)
}
}
View on GitHub (pinned to 843d9dc814)
Solutions
- Check the actual Go type reported by '%T' in the message to identify what the driver delivered.
- Ensure the column type is TEXT/VARCHAR/JSON-as-string so drivers return []byte or string.
- Add a case for the reported type (e.g. json.RawMessage) to the Scan switch if your driver requires it.
- Repair any rows containing non-JSON-array data in that column.
Example fix
// before
switch v := value.(type) {
case []byte:
return json.Unmarshal(v, (*[]string)(p))
case string:
return json.Unmarshal([]byte(v), (*[]string)(p))
}
// after (also accept driver-delivered raw JSON)
switch v := value.(type) {
case []byte:
return json.Unmarshal(v, (*[]string)(p))
case string:
return json.Unmarshal([]byte(v), (*[]string)(p))
case json.RawMessage:
return json.Unmarshal(v, (*[]string)(p))
} Defensive patterns
Strategy: type-guard
Type guard
// Guard before/while scanning
tv := reflect.TypeOf(value)
if value != nil && tv != nil && tv.Kind() != reflect.String && tv.Kind() != reflect.Slice {
return fmt.Errorf("paths column must arrive as string or []byte, got %T", value)
} Try / catch
if err := user.Paths.Scan(col); err != nil {
if strings.HasPrefix(err.Error(), "cannot scan") {
// log row id + driver name; likely column type drift
}
} Prevention
- Pin one column representation (TEXT) across all supported databases.
- Add migration tests that round-trip Paths through each supported driver.
- Never write non-JSON data into the paths column.
- When swapping DB drivers, run a smoke test that loads a row containing Paths.
When it happens
Trigger: Reading a row where the paths column is stored as a non-textual type (e.g. a JSON/JSONB column returned as a structured value by the driver, or a number) so the driver passes something other than []byte/string/nil to Scan.
Common situations: Switching database backends (SQLite <-> Postgres) where JSONB arrives typed differently; a migration that changed the column type; hand-edited rows with invalid content; using a driver version that changed its scan representation.
Related errors
- cannot scan %T
- [doubao_new] decode response failed (status: %s, content-typ
- failed to parse response: %v
- check share id availability: %w
- missing cookie or qrcode account
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/da4c76e53b4fe9ec.
Report an issue: GitHub.