{"record":{"id":"da4c76e53b4fe9ec","repo":"AlistGo/alist","slug":"cannot-scan-t","errorCode":null,"errorMessage":"cannot scan %T","messagePattern":"cannot scan %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/model/paths.go","lineNumber":25,"sourceCode":")\n\ntype Paths []string\n\nfunc (p Paths) Value() (driver.Value, error) {\n\treturn json.Marshal([]string(p))\n}\n\nfunc (p *Paths) Scan(value interface{}) error {\n\tswitch v := value.(type) {\n\tcase []byte:\n\t\treturn json.Unmarshal(v, (*[]string)(p))\n\tcase string:\n\t\treturn json.Unmarshal([]byte(v), (*[]string)(p))\n\tcase nil:\n\t\t*p = nil\n\t\treturn nil\n\tdefault:\n\t\treturn fmt.Errorf(\"cannot scan %T\", value)\n\t}\n}\n","sourceCodeStart":7,"sourceCodeEnd":28,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/internal/model/paths.go#L7-L28","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nswitch v := value.(type) {\ncase []byte:\n    return json.Unmarshal(v, (*[]string)(p))\ncase string:\n    return json.Unmarshal([]byte(v), (*[]string)(p))\n}\n\n// after (also accept driver-delivered raw JSON)\nswitch v := value.(type) {\ncase []byte:\n    return json.Unmarshal(v, (*[]string)(p))\ncase string:\n    return json.Unmarshal([]byte(v), (*[]string)(p))\ncase json.RawMessage:\n    return json.Unmarshal(v, (*[]string)(p))\n}","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"// Guard before/while scanning\ntv := reflect.TypeOf(value)\nif value != nil && tv != nil && tv.Kind() != reflect.String && tv.Kind() != reflect.Slice {\n    return fmt.Errorf(\"paths column must arrive as string or []byte, got %T\", value)\n}","tryCatchPattern":"if err := user.Paths.Scan(col); err != nil {\n    if strings.HasPrefix(err.Error(), \"cannot scan\") {\n        // log row id + driver name; likely column type drift\n    }\n}","preventionTips":["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."],"tags":["gorm","database","serialization","json","go"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}