{"record":{"id":"01cc874c04a071d4","repo":"vxcontrol/pentagi","slug":"user-hash-mismatch-session-invalid-for-this-inst","errorCode":null,"errorMessage":"user hash mismatch - session invalid for this installation","messagePattern":"user hash mismatch - session invalid for this installation","errorType":"http","errorClass":null,"httpStatus":401,"severity":"warning","filePath":"backend/pkg/server/auth/auth_middleware.go","lineNumber":112,"sourceCode":"// error, so callers can log it at a quieter level.\nfunc isRoutineAuthFailure(authErr error) bool {\n\treturn errors.Is(authErr, errCookieClaimInvalid) ||\n\t\terrors.Is(authErr, errSessionExpired) ||\n\t\terrors.Is(authErr, errUserHashMismatch)\n}\n\n// errCookieClaimInvalid is returned by tryUserCookieAuthentication when the\n// session cookie is present but missing one or more required claims (expired\n// or otherwise invalid session) - a routine, expected condition.\n//\n// errSessionExpired and errUserHashMismatch mark the same category of routine\n// session/token invalidation, just detected a bit later during validation: a\n// session past its TTL, or a stored hash that no longer matches the user\n// record (e.g. after a password change or a test database reseed).\nvar (\n\terrCookieClaimInvalid = errors.New(\"cookie claim invalid\")\n\terrSessionExpired     = errors.New(\"session expired\")\n\terrUserHashMismatch   = errors.New(\"user hash mismatch\")\n)\n\nfunc (p *AuthMiddleware) tryUserCookieAuthentication(c *gin.Context) (authResult, error) {\n\tsessionObject, exists := c.Get(sessions.DefaultKey)\n\tif !exists {\n\t\treturn authResultSkip, errors.New(\"can't find session object\")\n\t}\n\n\tsession, ok := sessionObject.(sessions.Session)\n\tif !ok {\n\t\treturn authResultFail, errors.New(\"not a session object\")\n\t}\n\n\tuid := session.Get(\"uid\")\n\tuhash := session.Get(\"uhash\")\n\trid := session.Get(\"rid\")\n\tprm := session.Get(\"prm\")\n\texp := session.Get(\"exp\")","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/auth/auth_middleware.go#L94-L130","documentation":"errUserHashMismatch means the hash stored in the session does not match the hash stored for the user in the database. The hash is invalidated whenever the user record changes materially (e.g. password change) or the database is reseeded, so sessions issued before that become invalid. This prevents a stolen/old session from remaining valid after credential changes.","triggerScenarios":"Making an API request with a session cookie created before the user's password was changed, or against a database that was re-seeded/recreated (common in dev/test) so the stored user hash differs from the one embedded in the cookie.","commonSituations":"Developer changes a password in one tab; other tabs keep failing with 401. CI/test databases are reseeded while a browser still holds an old session cookie. Restoring a DB dump invalidates all previously issued sessions.","solutions":["Log out and log in again — a new session will embed the current user hash","If it appears right after a password change, ensure the client clears/refreshes the session after the change-password call","In test environments, clear cookies after reseeding the database"],"exampleFix":"// before\nawait api.changePassword(newPass); // session not refreshed\n// after\nawait api.changePassword(newPass);\nawait api.logout();\nwindow.location.href = '/login';","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await api.call();\n} catch (e) {\n  if (e.response?.status === 401) {\n    // likely password changed or DB reseeded — force re-login\n    await api.logout();\n    window.location.href = '/login';\n  }\n}","preventionTips":["Log out all sessions (or force re-login) immediately after a password change","Clear browser cookies whenever reseeding/restoring a dev or test database","Communicate expected session invalidation to users after credential changes"],"tags":["authentication","session","password-change"],"backgroundTag":"session-hash-mismatch","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}