{"record":{"id":"3fb45f475f681ca6","repo":"vxcontrol/pentagi","slug":"error-checking-user-status-w","errorCode":null,"errorMessage":"error checking user status: %w","messagePattern":"error checking user status: %w","errorType":"exception","errorClass":null,"httpStatus":500,"severity":"error","filePath":"backend/pkg/server/auth/auth_middleware.go","lineNumber":163,"sourceCode":"\n\texpVal, ok := exp.(int64)\n\tif !ok {\n\t\treturn authResultFail, errors.New(\"token claim invalid\")\n\t}\n\tif time.Now().Unix() > expVal {\n\t\treturn authResultFail, errSessionExpired\n\t}\n\n\t// Verify user hash matches database\n\tuserID := uid.(uint64)\n\tsessionHash := uhash.(string)\n\n\tdbHash, userStatus, err := p.userCache.GetUserHash(userID)\n\tif err != nil {\n\t\tif errors.Is(err, gorm.ErrRecordNotFound) {\n\t\t\treturn authResultFail, errors.New(\"user has been deleted\")\n\t\t}\n\t\treturn authResultFail, fmt.Errorf(\"error checking user status: %w\", err)\n\t}\n\n\tswitch userStatus {\n\tcase models.UserStatusBlocked:\n\t\treturn authResultFail, errors.New(\"user has been blocked\")\n\tcase models.UserStatusCreated:\n\t\treturn authResultFail, errors.New(\"user is not ready\")\n\tcase models.UserStatusActive:\n\t}\n\n\tif dbHash != sessionHash {\n\t\treturn authResultFail, fmt.Errorf(\"%w - session invalid for this installation\", errUserHashMismatch)\n\t}\n\n\tc.Set(\"prm\", prms)\n\tc.Set(\"uid\", userID)\n\tc.Set(\"uhash\", sessionHash)\n\tc.Set(\"rid\", rid.(uint64))","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/auth/auth_middleware.go#L145-L181","documentation":"In tryUserCookieAuthentication, after the session cookie's JWT is validated, p.userCache.GetUserHash(userID) is called. Any error other than gorm.ErrRecordNotFound is wrapped as \"error checking user status: %w\" — the user's hash/status could not be fetched from the cache/backing store, so authentication cannot proceed.","triggerScenarios":"Database connection failure, timeout, or serialization error while reading the user row through the cache; cache misconfiguration; transient backend (Postgres) outage during a cookie-authenticated request.","commonSituations":"Postgres restarted or unreachable; connection pool exhausted under load; cache layer returning unexpected errors; migrations not run so the users table/columns are missing.","solutions":["Check backend logs for the wrapped %w cause and verify PostgreSQL connectivity (docker compose ps, connection env vars)","Retry the request if the cause is transient (pool exhaustion, restart in progress)","Run database migrations (goose runs at startup) to ensure schema is current","Inspect userCache configuration and its underlying store for misconfiguration"],"exampleFix":"// before\n// DB unreachable\ndocker compose stop db\n// after\ndocker compose up -d db && docker compose up -d pentagi","handlingStrategy":"retry","validationCode":null,"typeGuard":"func isDBStatusError(err error) bool {\n    return err != nil && strings.Contains(err.Error(), \"error checking user status:\") &&\n        !errors.Is(err, gorm.ErrRecordNotFound)\n}","tryCatchPattern":"result, err := doRequest()\nif err != nil && strings.Contains(err.Error(), \"error checking user status\") {\n    if isTransient(err) {\n        time.Sleep(backoff)\n        return doRequest() // retry during transient DB issues\n    }\n}\nreturn result, err","preventionTips":["Monitor PostgreSQL health and set readiness probes so traffic stops during outages","Size the DB connection pool for peak concurrent authenticated requests","Ensure migrations run at startup and complete before serving traffic","Alert on cache/DB error rates from the auth middleware"],"tags":["database","authentication","cache"],"backgroundTag":"database-unavailable","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}