{"record":{"id":"65132c1d9b41100e","repo":"juicedata/juicefs","slug":"smembers-s-s","errorCode":null,"errorMessage":"SMembers %s: %s","messagePattern":"SMembers (.+?): (.+?)","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/meta/redis.go","lineNumber":552,"sourceCode":"}\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\n\t\ts.Plocks = make([]Plock, 0, len(locks))\n\t\tfor _, lock := range locks {\n\t\t\towners, err := m.rdb.HGetAll(ctx, lock).Result()\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"HGetAll %s: %s\", lock, err)\n\t\t\t}","sourceCodeStart":534,"sourceCodeEnd":570,"githubUrl":"https://github.com/juicedata/juicefs/blob/c9a67b23e8e08ec23ec331aa6f1675e2319e921c/pkg/meta/redis.go#L534-L570","documentation":"When fetching session detail (detail=true), getSession reads the set of sustained (held-open but not yet committed) chunk slices via SMembers on the session's `sustained` key. If Redis returns a non-Nil error for that read, it is wrapped and returned as `SMembers <sid>: <err>`. This is a Redis-level failure (connection, cluster downscaled, key type mismatch, NOAUTH, READONLY, etc.), not a data corruption issue.","triggerScenarios":"Calling `juicefs status <meta-url> --session <sid>` (GetSession/ListSessions with detail) while the Redis connection fails mid-request, the sustained key has been replaced with a non-set type, Redis is in READONLY replica mode, or auth/ACL denies access to the key.","commonSituations":"1) Redis failover/timeout during the status command (MOVED, cluster resharding). 2) Wrong password/ACL after a config change (NOAUTH/WRONGPASS). 3) Querying a read-only replica or a proxy that rejects SMembers. 4) External tooling wrote a wrong-typed key at the sustained prefix.","solutions":["Check Redis connectivity/auth from the client: run `redis-cli -u <meta-url> SMEMBERS <anykey>` and resolve NOAUTH/WRONGPASS/READONLY errors first.","If cluster MOVED/resharding, point juicefs at the correct cluster endpoints or retry after resharding completes; ensure `juicefs` connects to the primary, not a replica.","Verify no external process overwrote the `sustained*` keys with wrong types (TYPE check); fix or delete the wrongly typed key.","If the session is stale/crashed, simply remove the session record instead of fetching details.","Retry the status command on transient network errors; add --no-detail by listing without detail to skip SMembers entirely where supported."],"exampleFix":"// before: status fails with SMembers <sid>: READONLY You can't write against a read only replica.\n// after: point the client at the primary endpoint\n// before\njuicefs status redis://replica-host:6379/1 --session 42\n// after\njuicefs status redis://primary-host:6379/1 --session 42","handlingStrategy":"try-catch","validationCode":"// Precheck Redis health and auth from the same endpoint used by juicefs\n$ redis-cli -u \"$META_URL\" PING\n$ redis-cli -u \"$META_URL\" SMEMBERS <prefix>sustained<sid>","typeGuard":null,"tryCatchPattern":"sess, err := metaCli.GetSession(sid, true)\nif err != nil {\n\tvar netErr net.Error\n\tif errors.As(err, &netErr) || strings.Contains(err.Error(), \"SMembers\") {\n\t\t// transient Redis failure: back off and retry\n\t\ttime.Sleep(2 * time.Second)\n\t\tsess, err = metaCli.GetSession(sid, true)\n\t}\n\tif err != nil { return err }\n}","preventionTips":["Point status/listing at the Redis primary, not a replica (READONLY errors).","Keep credentials/ACLs consistent for all juicefs operations against the same volume.","Avoid running status commands during cluster resharding or failover windows.","Verify key types before manual Redis maintenance (TYPE check on sustained* keys).","Retry once on transient network errors before reporting failure."],"tags":["redis","network","session"],"backgroundTag":"database-query-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"}