{"record":{"id":"88e2a4ebfead5331","repo":"AdguardTeam/AdGuardHome","slug":"iterating-over-sessions-w","errorCode":null,"errorMessage":"iterating over sessions: %w","messagePattern":"iterating over sessions: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/aghuser/sessionstorage.go","lineNumber":204,"sourceCode":"\t\t\"loading sessions from db\",\n\t\t\"stored\", len(ds.sessions),\n\t\t\"removed\", removed,\n\t)\n\n\treturn nil\n}\n\n// processSessions iterates over the sessions bucket and loads or removes\n// sessions as needed.\nfunc (ds *DefaultSessionStorage) processSessions(\n\tctx context.Context,\n\tbkt *bbolt.Bucket,\n) (removed int, err error) {\n\tinvalidSessions := [][]byte{}\n\n\terr = bkt.ForEach(ds.bboltSessionHandler(ctx, &invalidSessions))\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"iterating over sessions: %w\", err)\n\t}\n\n\tvar errs []error\n\tfor _, s := range invalidSessions {\n\t\tif err = bkt.Delete(s); err != nil {\n\t\t\terrs = append(errs, err)\n\t\t}\n\t}\n\n\tif err = errors.Join(errs...); err != nil {\n\t\treturn 0, fmt.Errorf(\"deleting sessions: %w\", err)\n\t}\n\n\treturn len(invalidSessions), nil\n}\n\n// bboltSessionHandler returns a function for [bbolt.Bucket.ForEach] that\n// iterates over stored sessions, deserializes them, and logs any errors","sourceCodeStart":186,"sourceCodeEnd":222,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/aghuser/sessionstorage.go#L186-L222","documentation":"Iterating the sessions bucket with bbolt's ForEach aborted because the per-key handler returned an error. The wrapped error originates from bboltSessionHandler decoding each stored session (e.g., gob/JSON unmarshal failure on a session value).","triggerScenarios":"A stored session key/value pair in the bucket cannot be decoded by the current session handler: schema drift after upgrade, corrupted entry, or a value written by a different storage version.","commonSituations":"Upgrading the app across a session-structure change without clearing sessions.db; crash-corrupted bbolt entries; mixed-version replicas sharing a data directory.","solutions":["Decode the wrapped error to find which entry failed; inspect bucket keys with a bbolt inspection tool","Reset the sessions store (users re-login) if entries are unsalvageable","Ship schema migrations or versioned decoders for session records"],"exampleFix":"# before\n# old-format session entries fail decode\n# after\nbbolt buckets -path sessions.db -bucket sessions # inspect, then reset if needed","handlingStrategy":"fallback","validationCode":"// pre-upgrade: decode all bucket values with the target session type; abort with a clear report on failure","typeGuard":null,"tryCatchPattern":"if err := ds.processSessions(ctx, bkt); err != nil {\n    if strings.Contains(err.Error(), \"iterating over sessions\") { reset sessions store as a fallback (users re-login) }\n}","preventionTips":["Use versioned, forward-compatible session encodings","Test upgrades against production-shaped session data before deploy"],"tags":["sessions","bbolt","iteration","deserialization"],"backgroundTag":"schema-deserialization-failed","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}