getredash/redash · error
User not found.
Error message
User not found.
What it means
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.
Source
Thrown at redash/handlers/permissions.py:52
return result
def post(self, object_type, object_id):
model = get_model_from_type(object_type)
obj = get_object_or_404(model.get_by_id_and_org, object_id, self.current_org)
require_admin_or_owner(obj.user_id)
req = request.get_json(True)
access_type = req["access_type"]
if access_type not in ACCESS_TYPES:
abort(400, message="Unknown access type.")
try:
grantee = User.get_by_id_and_org(req["user_id"], self.current_org)
except NoResultFound:
abort(400, message="User not found.")
permission = AccessPermission.grant(obj, access_type, grantee, self.current_user)
db.session.commit()
self.record_event(
{
"action": "grant_permission",
"object_id": object_id,
"object_type": object_type,
"grantee": grantee.id,
"access_type": access_type,
}
)
return permission.to_dict()
def delete(self, object_type, object_id):
model = get_model_from_type(object_type)View on GitHub (pinned to ca79fe988d)
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.
Example fix
# before
client.post(f'/api/queries/{qid}/permissions', json={'user_id': 12345, 'access_type': 'modify'})
# after
users = {u['email']: u['id'] for u in client.get('/api/users')['results']}
client.post(f'/api/queries/{qid}/permissions', json={'user_id': users['teammate@corp.com'], 'access_type': 'modify'}) Defensive patterns
Strategy: validation
Validate before calling
org_user_ids = {u['id'] for u in client.get('/api/users')['results']}
if user_id not in org_user_ids:
resolve_or_skip(user_id) Try / catch
try:
client.post(perm_url, json=payload)
except HTTPError as e:
if e.response.status_code == 400 and 'User not found' in e.response.text:
remove_user_from_grant_list(user_id)
else:
raise Prevention
- Resolve user ids from /api/users at grant time instead of caching.
- Remember lookups are org-scoped: cross-org ids always fail.
When it happens
Trigger: POST /api/<object>/<id>/permissions with a user_id that is deleted, belongs to a different org, or is a plain typo/nonexistent id.
Common situations: 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.
Related errors
- Can't modify built-in groups.
- Unknown access type.
- You do not have access to data source: %s.
- You do not have access to query id %s.
- Query id {} not found.
AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28).
Data as JSON: /api/errors/dc855d749dd388e6.
Report an issue: GitHub.