vxcontrol/pentagi · warning
user hash mismatch - session invalid for this installation
Error message
user hash mismatch - session invalid for this installation
What it means
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.
Source
Thrown at backend/pkg/server/auth/auth_middleware.go:112
// error, so callers can log it at a quieter level.
func isRoutineAuthFailure(authErr error) bool {
return errors.Is(authErr, errCookieClaimInvalid) ||
errors.Is(authErr, errSessionExpired) ||
errors.Is(authErr, errUserHashMismatch)
}
// errCookieClaimInvalid is returned by tryUserCookieAuthentication when the
// session cookie is present but missing one or more required claims (expired
// or otherwise invalid session) - a routine, expected condition.
//
// errSessionExpired and errUserHashMismatch mark the same category of routine
// session/token invalidation, just detected a bit later during validation: a
// session past its TTL, or a stored hash that no longer matches the user
// record (e.g. after a password change or a test database reseed).
var (
errCookieClaimInvalid = errors.New("cookie claim invalid")
errSessionExpired = errors.New("session expired")
errUserHashMismatch = errors.New("user hash mismatch")
)
func (p *AuthMiddleware) tryUserCookieAuthentication(c *gin.Context) (authResult, error) {
sessionObject, exists := c.Get(sessions.DefaultKey)
if !exists {
return authResultSkip, errors.New("can't find session object")
}
session, ok := sessionObject.(sessions.Session)
if !ok {
return authResultFail, errors.New("not a session object")
}
uid := session.Get("uid")
uhash := session.Get("uhash")
rid := session.Get("rid")
prm := session.Get("prm")
exp := session.Get("exp")View on GitHub (pinned to ea665308ba)
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
Example fix
// before await api.changePassword(newPass); // session not refreshed // after await api.changePassword(newPass); await api.logout(); window.location.href = '/login';
Defensive patterns
Strategy: try-catch
Try / catch
try {
await api.call();
} catch (e) {
if (e.response?.status === 401) {
// likely password changed or DB reseeded — force re-login
await api.logout();
window.location.href = '/login';
}
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cookie claim invalid
- session expired
- user has been deleted
- %w - session invalid for this installation
- user has been blocked
AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01).
Data as JSON: /api/errors/01cc874c04a071d4.
Report an issue: GitHub.