AlistGo/alist · error

cannot scan %T

Error message

cannot scan %T

What it means

Same Scanner-hook pattern as Paths.Scan but for the Roles type ([]int stored as JSON). (*Roles).Scan only accepts []byte, string, or nil; any other driver value type triggers 'cannot scan %T'. It is the deserialization boundary between the DB column and the []int role list.

Source

Thrown at internal/model/roles.go:25

)

type Roles []int

func (r Roles) Value() (driver.Value, error) {
	return json.Marshal([]int(r))
}

func (r *Roles) Scan(value interface{}) error {
	switch v := value.(type) {
	case []byte:
		return json.Unmarshal(v, (*[]int)(r))
	case string:
		return json.Unmarshal([]byte(v), (*[]int)(r))
	case nil:
		*r = nil
		return nil
	default:
		return fmt.Errorf("cannot scan %T", value)
	}
}

func (r Roles) Contains(role int) bool {
	for _, v := range r {
		if v == role {
			return true
		}
	}
	return false
}

View on GitHub (pinned to 843d9dc814)

Solutions

  1. Look at the '%T' in the message to see the concrete type your driver returns.
  2. Keep the roles column as a text/JSON string type so Scan receives []byte or string.
  3. Extend the type switch with the driver-specific type if needed.
  4. Fix rows whose roles column is not a valid JSON array of integers.

Example fix

// before
case string:
    return json.Unmarshal([]byte(v), (*[]int)(r))

// after
case string:
    return json.Unmarshal([]byte(v), (*[]int)(r))
case json.RawMessage:
    return json.Unmarshal(v, (*[]int)(r))
Defensive patterns

Strategy: type-guard

Type guard

tv := reflect.TypeOf(value)
if value != nil && tv != nil && tv.Kind() != reflect.String && tv.Kind() != reflect.Slice {
    return fmt.Errorf("roles column must arrive as string or []byte, got %T", value)
}

Try / catch

if err := user.Roles.Scan(col); err != nil {
    if strings.HasPrefix(err.Error(), "cannot scan") {
        // inspect %T, fix column type or extend the switch
    }
}

Prevention

When it happens

Trigger: Loading a user row where the roles column is returned by the driver as a typed JSON value, a number, or another non-text type; the column contains data but the driver does not present it as bytes/string.

Common situations: Database backend change altering how JSON columns are scanned; Postgres JSONB via a driver that returns a non-[]byte representation; schema drifted after migrations; corrupted column content.

Related errors


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