{"record":{"id":"dc855d749dd388e6","repo":"getredash/redash","slug":"user-not-found","errorCode":null,"errorMessage":"User not found.","messagePattern":"User not found\\.","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"redash/handlers/permissions.py","lineNumber":52,"sourceCode":"        return result\n\n    def post(self, object_type, object_id):\n        model = get_model_from_type(object_type)\n        obj = get_object_or_404(model.get_by_id_and_org, object_id, self.current_org)\n\n        require_admin_or_owner(obj.user_id)\n\n        req = request.get_json(True)\n\n        access_type = req[\"access_type\"]\n\n        if access_type not in ACCESS_TYPES:\n            abort(400, message=\"Unknown access type.\")\n\n        try:\n            grantee = User.get_by_id_and_org(req[\"user_id\"], self.current_org)\n        except NoResultFound:\n            abort(400, message=\"User not found.\")\n\n        permission = AccessPermission.grant(obj, access_type, grantee, self.current_user)\n        db.session.commit()\n\n        self.record_event(\n            {\n                \"action\": \"grant_permission\",\n                \"object_id\": object_id,\n                \"object_type\": object_type,\n                \"grantee\": grantee.id,\n                \"access_type\": access_type,\n            }\n        )\n\n        return permission.to_dict()\n\n    def delete(self, object_type, object_id):\n        model = get_model_from_type(object_type)","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/handlers/permissions.py#L34-L70","documentation":"Raised by PermissionResource.post in redash/handlers/permissions.py when User.get_by_id_and_org raises NoResultFound for the supplied user_id — i.e. no user with that id exists in the current organization. The grant cannot proceed because the grantee must be a real org member.","triggerScenarios":"POST /api/<object>/<id>/permissions with a user_id that is deleted, belongs to a different org, or is a plain typo/nonexistent id.","commonSituations":"Stale user ids cached from before users were removed; multi-org deployments where the id exists but in another org; scripts using global ids instead of org-scoped ids.","solutions":["Verify the user exists in the same org: GET /api/users and match by id or email.","Refresh user ids at run time instead of caching them; look up by email if ids are unstable.","Handle the 400 by skipping or re-resolving the user in automation scripts."],"exampleFix":"# before\nclient.post(f'/api/queries/{qid}/permissions', json={'user_id': 12345, 'access_type': 'modify'})\n\n# after\nusers = {u['email']: u['id'] for u in client.get('/api/users')['results']}\nclient.post(f'/api/queries/{qid}/permissions', json={'user_id': users['teammate@corp.com'], 'access_type': 'modify'})","handlingStrategy":"validation","validationCode":"org_user_ids = {u['id'] for u in client.get('/api/users')['results']}\nif user_id not in org_user_ids:\n    resolve_or_skip(user_id)","typeGuard":null,"tryCatchPattern":"try:\n    client.post(perm_url, json=payload)\nexcept HTTPError as e:\n    if e.response.status_code == 400 and 'User not found' in e.response.text:\n        remove_user_from_grant_list(user_id)\n    else:\n        raise","preventionTips":["Resolve user ids from /api/users at grant time instead of caching.","Remember lookups are org-scoped: cross-org ids always fail."],"tags":["redash","permissions","user-not-found","bad-request"],"backgroundTag":"referenced-entity-not-found","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}