{"record":{"id":"6533e1595ca9c6d9","repo":"juicedata/juicefs","slug":"corrupted-session-info-json-error-s","errorCode":null,"errorMessage":"corrupted session info; json error: %s","messagePattern":"corrupted session info; json error: (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/redis.go","lineNumber":546,"sourceCode":"\t\t\t})\n\t\t\treturn err\n\t\t}\n\t}, name)\n\n\treturn changed, err\n}\n\nfunc (m *redisMeta) getSession(sid string, detail bool) (*Session, error) {\n\tctx := Background()\n\tinfo, err := m.rdb.HGet(ctx, m.sessionInfos(), sid).Bytes()\n\tif err == redis.Nil { // legacy client has no info\n\t\tinfo = []byte(\"{}\")\n\t} else if err != nil {\n\t\treturn nil, fmt.Errorf(\"HGet sessionInfos %s: %s\", sid, err)\n\t}\n\tvar s Session\n\tif err := json.Unmarshal(info, &s); err != nil {\n\t\treturn nil, fmt.Errorf(\"corrupted session info; json error: %s\", err)\n\t}\n\ts.Sid, _ = strconv.ParseUint(sid, 10, 64)\n\tif detail {\n\t\tinodes, err := m.rdb.SMembers(ctx, m.sustained(s.Sid)).Result()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"SMembers %s: %s\", sid, err)\n\t\t}\n\t\ts.Sustained = make([]Ino, 0, len(inodes))\n\t\tfor _, sinode := range inodes {\n\t\t\tinode, _ := strconv.ParseUint(sinode, 10, 64)\n\t\t\ts.Sustained = append(s.Sustained, Ino(inode))\n\t\t}\n\n\t\tlocks, err := m.rdb.SMembers(ctx, m.lockedKey(s.Sid)).Result()\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"SMembers %s: %s\", sid, err)\n\t\t}\n\t\ts.Flocks = make([]Flock, 0, len(locks)) // greedy","sourceCodeStart":528,"sourceCodeEnd":564,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/redis.go#L528-L564","documentation":"getSession reads a client session's JSON blob from the Redis hash `sessionInfos` and unmarshals it into a meta.Session. If the stored value is not valid JSON (or doesn't match the Session schema), json.Unmarshal fails and this error is returned, signaling the persisted session record is corrupted. It is thrown by both `juicefs status <mountpoint>`/session listing paths (GetSession, ListSessions).","triggerScenarios":"Running `juicefs status <meta-url> --session <sid>` or `juicefs status <meta-url>` (which lists all sessions via ListSessions -> getSession) when the HGET sessionInfos <sid> value in Redis is corrupt or was written by an incompatible/older client with a different JSON layout, or the key was modified/deleted externally.","commonSituations":"1) Someone manually edited or trimmed Redis data (e.g. via redis-cli, or a Redis RDB/AOF restore that truncated values). 2) Mixed-version clusters where a newer client wrote fields an older reader can't parse (rare, since JSON unmarshal is forward-tolerant) or where a third-party tool rewrote the hash. 3) Non-JSON bytes in the sessionInfos hash from a broken client or external writer.","solutions":["Identify the offending session id from the error, then inspect the raw value: redis-cli HGET <prefix>sessionInfos <sid> — if it's invalid JSON, the record is corrupt.","Check which client owns the session (`juicefs status` lists sessions); if the session is stale (mount crashed long ago), remove it with `juicefs rmr --session`/`juicefs status` tooling or delete the stale session record so listing can proceed.","Verify all JuiceFS clients in the cluster run a compatible version; upgrade older clients and remount so session info is rewritten in the current format.","If corruption came from a bad Redis restore, restore from a healthy RDB/AOF backup.","As a workaround, tolerate the bad record by skipping failed sessions when listing, or drop the single corrupt hash field: redis-cli HDEL <prefix>sessionInfos <sid>."],"exampleFix":"// admin-side cleanup once the corrupt session id is known\n// before: juicefs status redis://... fails with \"corrupted session info\"\n// after:\n$ redis-cli -u redis://... HGET sessionInfos 42        # inspect\n$ redis-cli -u redis://... HDEL sessionInfos 42       # drop corrupt record\n$ juicefs status redis://...                           # succeeds","handlingStrategy":"validation","validationCode":"// Check the raw session blob before relying on tooling output\n$ redis-cli -u \"$META_URL\" HGET <prefix>sessionInfos <sid> | python3 -m json.tool\n# exit 0 => valid JSON; error => corrupt record","typeGuard":"func sessionInfoLooksLikeJSON(raw []byte) bool {\n\tvar s meta.Session\n\treturn json.Unmarshal(raw, &s) == nil\n}","tryCatchPattern":"sess, err := metaCli.GetSession(sid, true)\nif err != nil {\n\tif strings.Contains(err.Error(), \"corrupted session info\") {\n\t\tlog.Warnf(\"skipping corrupt session %d: %v\", sid, err)\n\t\treturn nil // skip and continue listing other sessions\n\t}\n\treturn err\n}","preventionTips":["Never hand-edit Redis keys belonging to JuiceFS; use the provided CLI commands.","Keep all clients on a compatible JuiceFS version before rolling upgrades.","Back up Redis (RDB/AOF) before any restore or migration.","If a listing fails on one session, enumerate and delete just the corrupt sessionInfos hash field instead of wiping the DB.","Monitor for crashed mounts and clean stale sessions promptly via `juicefs gc`/rmr tooling."],"tags":["redis","metadata","json","session"],"backgroundTag":"json-unmarshal-failed","analyzedSha":"c9a67b23e8e08ec23ec331aa6f1675e2319e921c","analyzedAt":"2026-09-06T17:55:48.476Z","contentChangedAt":"2026-09-06T17:55:48.476Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}