{"record":{"id":"69570cd0ecd6b9ba","repo":"AdguardTeam/AdGuardHome","slug":"expired-session-w","errorCode":null,"errorMessage":"expired session: %w","messagePattern":"expired session: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/aghuser/sessionstorage.go","lineNumber":393,"sourceCode":"\n\treturn nil\n}\n\n// FindByToken implements the [SessionStorage] interface for *DefaultSessionStorage.\nfunc (ds *DefaultSessionStorage) FindByToken(ctx context.Context, t SessionToken) (s *Session, err error) {\n\tds.mu.Lock()\n\tdefer ds.mu.Unlock()\n\n\ts, ok := ds.sessions[t]\n\tif !ok {\n\t\treturn nil, nil\n\t}\n\n\tnow := ds.clock.Now()\n\tif now.After(s.Expire) {\n\t\terr = ds.deleteByToken(ctx, t)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"expired session: %w\", err)\n\t\t}\n\n\t\treturn nil, nil\n\t}\n\n\treturn s, nil\n}\n\n// DeleteByToken implements the [SessionStorage] interface for\n// *DefaultSessionStorage.\nfunc (ds *DefaultSessionStorage) DeleteByToken(ctx context.Context, t SessionToken) (err error) {\n\tds.mu.Lock()\n\tdefer ds.mu.Unlock()\n\n\t// Don't wrap the error because it's informative enough as is.\n\treturn ds.deleteByToken(ctx, t)\n}\n","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/AdguardTeam/AdGuardHome/blob/b41aefbe51c8dde65e2c50f093996afa0502edf9/internal/aghuser/sessionstorage.go#L375-L411","documentation":"FindByToken found a session that is expired, attempted to delete it via deleteByToken, and that deletion itself failed. The wrapped error comes from remove() (begin/rollback/delete/commit chain). The user-visible effect is that expired sessions cannot be purged from the db.","triggerScenarios":"A request presents an expired session token while the db is unwritable, locked, or the bucket is missing ('no bucket').","commonSituations":"Disk full or read-only; second instance locking the db; sessions.db deleted out from under a running process so the bucket no longer exists.","solutions":["Restore writability of the data directory (space, permissions, locks)","Ensure only one process owns the db file","If the db file was removed manually while running, restart the service to reopen it"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// expired-session cleanup failure should not fail the request; treat as anonymous\nif err != nil && strings.Contains(err.Error(), \"expired session\") { return nil, aghauth.ErrNoUser }","preventionTips":["Keep the db writable so expiry cleanup works","Don't delete work-dir files under a running process"],"tags":["bbolt","session-expiry","delete"],"backgroundTag":"session-expired","analyzedSha":"b41aefbe51c8dde65e2c50f093996afa0502edf9","analyzedAt":"2026-08-27T04:57:55.097Z","schemaVersion":2},"datasetVersion":"2026-08-27T08:17:20.692Z"}