getredash/redash · error · PermissionError

You do not have access to query id {}.

Error message

You do not have access to query id {}.

What it means

Raised by _load_query (redash/query_runner/query_results.py:54) as a PermissionError when the query is in the user's organization but the user lacks view-only access to the query's data source. Access is evaluated with has_access(query.data_source, user, view_only), so group membership on the data source governs this path.

Source

Thrown at redash/query_runner/query_results.py:54

    queries = re.findall(r"(?:join|from)\s+query_(\d+)", query, re.IGNORECASE)
    return [int(q) for q in queries]


def extract_cached_query_ids(query):
    queries = re.findall(r"(?:join|from)\s+cached_query_(\d+)", query, re.IGNORECASE)
    return [int(q) for q in queries]


def _load_query(user, query_id):
    query = models.Query.get_by_id(query_id)

    if user.org_id != query.org_id:
        raise PermissionError("Query id {} not found.".format(query.id))

    # TODO: this duplicates some of the logic we already have in the redash.handlers.query_results.
    # We should merge it so it's consistent.
    if not has_access(query.data_source, user, view_only):
        raise PermissionError("You do not have access to query id {}.".format(query.id))

    return query


def replace_query_parameters(query_text, params):
    qs = parse_qs(params)
    for key, value in qs.items():
        query_text = query_text.replace("{{{{{my_key}}}}}".format(my_key=key), value[0])
    return query_text


def get_query_results(user, query_id, bring_from_cache, params=None):
    query = _load_query(user, query_id)
    if bring_from_cache:
        if query.latest_query_data_id is not None:
            results = query.latest_query_data.data
        else:
            raise Exception("No cached result available for query {}.".format(query.id))

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Add the user (or their group) to the data source's groups with at least view-only access in Data Source settings
  2. Ask the query owner to duplicate the query onto a data source the user can access
  3. If you own the pipeline, catch PermissionError and surface an access-request message instead of a raw stack trace

Example fix

# before
results = get_query_results(user, query_id, bring_from_cache=True)
# after
from redash.permissions import has_access
query = models.Query.get_by_id(query_id)
if not has_access(query.data_source, user, not user.is_admin() if False else view_only):
    raise HTTPError(403)
results = get_query_results(user, query_id, bring_from_cache=True)
Defensive patterns

Strategy: try-catch

Validate before calling

from redash import models
from redash.permissions import has_access, view_only
query = models.Query.get_by_id(query_id)
if query.org_id != user.org_id or not has_access(query.data_source, user, view_only):
    return error_response(403, 'no access to query')

Try / catch

try:
    results = get_query_results(user, qid, bring_from_cache)
except PermissionError as e:
    return error_response(403, str(e))

Prevention

When it happens

Trigger: Calling get_query_results / query_results runner where the user is not in any group that has (at least view-only) permissions on the query's data source; a user with a personal-only or restricted data source running a query that references it via query id.

Common situations: Query results loader ('load results of query X') pointed at a data source restricted to another group; newly provisioned users missing group membership; admins moving a query to a more restricted data source.

Understand the failure class

Background: Permission denied / not authorized / 403 Forbidden: access-control rejections when the caller lacks the required role, grant, or ownership — this error's family across 18 libraries.

Related errors


AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28). Data as JSON: /api/errors/0d39dfefa7cf3719. Report an issue: GitHub.