{"record":{"id":"4d99cb68e87a332a","repo":"getredash/redash","slug":"not-found","errorCode":null,"errorMessage":"Not found","messagePattern":"Not found","errorType":"http","errorClass":null,"httpStatus":404,"severity":"error","filePath":"redash/handlers/users.py","lineNumber":173,"sourceCode":"        self.record_event({\"action\": \"create\", \"object_id\": user.id, \"object_type\": \"user\"})\n\n        should_send_invitation = \"no_invite\" not in request.args\n        return invite_user(self.current_org, self.current_user, user, send_email=should_send_invitation)\n\n\nclass UserInviteResource(BaseResource):\n    @require_admin\n    def post(self, user_id):\n        user = models.User.get_by_id_and_org(user_id, self.current_org)\n        return invite_user(self.current_org, self.current_user, user)\n\n\nclass UserResetPasswordResource(BaseResource):\n    @require_admin\n    def post(self, user_id):\n        user = models.User.get_by_id_and_org(user_id, self.current_org)\n        if user.is_disabled:\n            abort(404, message=\"Not found\")\n        reset_link = send_password_reset_email(user)\n\n        return {\"reset_link\": reset_link}\n\n\nclass UserRegenerateApiKeyResource(BaseResource):\n    def post(self, user_id):\n        user = models.User.get_by_id_and_org(user_id, self.current_org)\n        if user.is_disabled:\n            abort(404, message=\"Not found\")\n        if not is_admin_or_owner(user_id):\n            abort(403)\n\n        user.regenerate_api_key()\n        models.db.session.commit()\n\n        self.record_event({\"action\": \"regnerate_api_key\", \"object_id\": user.id, \"object_type\": \"user\"})\n","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/handlers/users.py#L155-L191","documentation":"Raised by UserResetPasswordResource.post in redash/handlers/users.py when an admin requests a password reset link for a user that exists but is disabled (is_disabled). The 404 deliberately hides disabled accounts rather than revealing their state.","triggerScenarios":"POST /api/users/<id>/reset_password where the user record has is_disabled=True (deactivated account).","commonSituations":"Offboarding flows that disable users while stale admin tooling still tries to reset their password; attempting to reset a password before re-enabling the account.","solutions":["Re-enable the user first (POST /api/users/<id> is_disabled=false), then request the reset link.","Verify the user's disabled state via GET /api/users/<id> before calling.","If the user should stay disabled, skip the reset entirely."],"exampleFix":"# before\nlink = client.post(f'/api/users/{uid}/reset_password')['reset_link']\n\n# after\nclient.post(f'/api/users/{uid}', json={'is_disabled': False})\nlink = client.post(f'/api/users/{uid}/reset_password')['reset_link']","handlingStrategy":"validation","validationCode":"u = client.get(f'/api/users/{uid}')\nif u.get('is_disabled'):\n    client.post(f'/api/users/{uid}', json={'is_disabled': False})\nlink = client.post(f'/api/users/{uid}/reset_password')['reset_link']","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Filter is_disabled users out of admin maintenance runs.","Re-enable before reset; the 404 intentionally hides disabled accounts."],"tags":["redash","users","password-reset","disabled-user","not-found"],"backgroundTag":"account-disabled","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}