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

  1. Check the actual Go type reported by '%T' in the message to identify what the driver delivered.
  2. Ensure the column type is TEXT/VARCHAR/JSON-as-string so drivers return []byte or string.
  3. Add a case for the reported type (e.g. json.RawMessage) to the Scan switch if your driver requires it.
  4. 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

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


AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15). Data as JSON: /api/errors/da4c76e53b4fe9ec. Report an issue: GitHub.