getredash/redash · warning · QueryParseError

'pagination' should be an object with a `type` property

Error message

'pagination' should be an object with a `type` property

What it means

Pagination for JSON URL queries is configured via a 'pagination' object whose required 'type' selects the strategy ('url' or 'token'). Pagination.from_config validates it is a dict with a string type; otherwise it raises QueryParseError with this message.

Source

Thrown at redash/query_runner/json_ds.py:237

    def _get_json_response(self, url, method, **request_options):
        response, error = self.get_response(url, http_method=method, **request_options)
        result = response.json() if error is None else {}
        return result, error


class RequestPagination:
    def next(self, url, request_options, response):
        """Checks the response for another page.

        Returns:
            has_more, next_url, next_request_options
        """
        return False, None, request_options

    @staticmethod
    def from_config(configuration, pagination):
        if not isinstance(pagination, dict) or not isinstance(pagination.get("type"), str):
            raise QueryParseError("'pagination' should be an object with a `type` property")

        if pagination["type"] == "url":
            return UrlPagination(pagination)
        elif pagination["type"] == "token":
            return TokenPagination(pagination)

        raise QueryParseError("Unknown 'pagination.type' {}".format(pagination["type"]))


class UrlPagination(RequestPagination):
    def __init__(self, pagination):
        self.path = pagination.get("path", "_links.next.href")
        if not isinstance(self.path, str):
            raise QueryParseError("'pagination.path' should be a string")

    def next(self, url, request_options, response):
        next_url = _apply_path_search(response, self.path, "")
        if not next_url:

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Use pagination: {type: url, ...} or pagination: {type: token, ...} with correct nesting
  2. Ensure 'type' is present and one of the two supported strings; fix indentation so pagination is a mapping

Example fix

# before
pagination:
  next_page: next
# after
pagination:
  type: token
  next_page: next
Defensive patterns

Strategy: type-guard

Validate before calling

def pagination_ok(q: dict) -> bool:
    p = q.get("pagination")
    return p is None or (isinstance(p, dict) and isinstance(p.get("type"), str))

Type guard

import yaml

def is_valid_json_ds_query(q: str) -> bool:
    try:
        parsed = yaml.safe_load(q)
    except yaml.YAMLError:
        return False
    if not isinstance(parsed, dict) or "url" not in parsed:
        return False
    p = parsed.get("pagination")
    return p is None or (isinstance(p, dict) and p.get("type") in ("url", "token"))

Prevention

When it happens

Trigger: Setting pagination: url (a string), pagination: [ ... ] (list), omitting 'type', or misspelling 'type' (e.g. 'kind') in the query YAML.

Common situations: Adapting pagination examples and dropping the type key, wrong indentation making pagination a scalar, or using an unsupported type value.

Related errors


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