{"record":{"id":"2ceb76ef020c9b0b","repo":"vxcontrol/pentagi","slug":"auth-inactiveuser","errorCode":"Auth.InactiveUser","errorMessage":"user is inactive","messagePattern":"user is inactive","errorType":"http","errorClass":null,"httpStatus":403,"severity":"warning","filePath":"backend/pkg/server/services/auth.go","lineNumber":140,"sourceCode":"\t} else if err = user.Valid(); err != nil {\n\t\tlogger.FromContext(c).WithError(err).Errorf(\"error validating user data '%s'\", user.Hash)\n\t\tresponse.Error(c, response.ErrAuthInvalidUserData, err)\n\t\treturn\n\t} else if user.RoleID == 100 {\n\t\tlogger.FromContext(c).WithError(err).Errorf(\"can't authorize external user '%s'\", user.Hash)\n\t\tresponse.Error(c, response.ErrAuthInvalidUserData, fmt.Errorf(\"user is external\"))\n\t\treturn\n\t}\n\n\tif err := bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(data.Password)); err != nil {\n\t\tlogger.FromContext(c).Errorf(\"error matching user input password\")\n\t\tresponse.Error(c, response.ErrAuthInvalidCredentials, err)\n\t\treturn\n\t}\n\n\tif user.Status != \"active\" {\n\t\tlogger.FromContext(c).Errorf(\"error checking active state for user '%s'\", user.Status)\n\t\tresponse.Error(c, response.ErrAuthInactiveUser, fmt.Errorf(\"user is inactive\"))\n\t\treturn\n\t}\n\n\tvar privs []string\n\terr := s.db.Table(\"privileges\").\n\t\tWhere(\"role_id = ?\", user.RoleID).\n\t\tPluck(\"name\", &privs).Error\n\tif err != nil {\n\t\tlogger.FromContext(c).WithError(err).Errorf(\"error getting user privileges list '%s'\", user.Hash)\n\t\tresponse.Error(c, response.ErrAuthInvalidServiceData, err)\n\t\treturn\n\t}\n\n\tuuid, err := rdb.MakeUuidStrFromHash(user.Hash)\n\tif err != nil {\n\t\tlogger.FromContext(c).WithError(err).Errorf(\"error validating user data '%s'\", user.Hash)\n\t\tresponse.Error(c, response.ErrAuthInvalidUserData, err)\n\t\treturn","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/server/services/auth.go#L122-L158","documentation":"AuthLogin compares the bcrypt password successfully but then rejects the account because its status is not 'active', returning the Auth.InactiveUser error code. Accounts can be in other statuses (e.g. disabled/deactivated) as an administrative control; only 'active' accounts may log in locally.","triggerScenarios":"POST to the local login endpoint with correct credentials for a user whose users.status is anything other than 'active' (e.g. 'disabled', 'inactive', 'blocked' set by an admin or automated deactivation).","commonSituations":"Admin disabled the account for policy reasons; automated cleanup deactivated stale users; a newly provisioned account not yet activated; user deactivated themselves and forgot.","solutions":["Ask an admin to set the account back to active: UPDATE users SET status='active' WHERE ...","Check with your administrator why the account was deactivated (audit logs).","If the account should stay disabled, use a different account.","Verify no automation/job is mass-deactivating accounts unexpectedly."],"exampleFix":"-- reactivate a user account\nUPDATE users SET status = 'active' WHERE hash = '<user-hash>';","handlingStrategy":"validation","validationCode":"// check account status before attempting login\nvar user models.User\nif err := db.Where(\"email = ?\", email).First(&user).Error; err == nil {\n    if user.Status != \"active\" {\n        return fmt.Errorf(\"account is %s; contact an administrator\", user.Status)\n    }\n}","typeGuard":"func isActivatableUser(u models.User) bool {\n    return u.Status == \"active\"\n}","tryCatchPattern":"_, err := auth.Login(ctx, data)\nvar respErr *response.Error\nif errors.As(err, &respErr) && respErr.Code == response.ErrAuthInactiveUser {\n    showUserMessage(\"Your account is deactivated. Please contact your administrator.\")\n    return\n}\nif err != nil { return err }","preventionTips":["Surface account status in admin tooling before users hit the login wall","Notify users when their account is deactivated","Review automated deactivation jobs for false positives","Only set status='active' through a controlled admin action"],"tags":["authentication","account-status","login","rbac"],"backgroundTag":"user-account-inactive","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}