getredash/redash · error · QueryParseError
'pagination.fields' should be a list of 2 field names
Error message
'pagination.fields' should be a list of 2 field names
What it means
TokenPagination requires 'pagination.fields' to be a list of exactly two strings: the field in the response holding the next-page token (default 'next_page_token') and the request parameter to send it in (default 'page_token'). Any other shape is rejected at construction.
Source
Thrown at redash/query_runner/json_ds.py:266
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:
return False, None, request_options
next_url = urljoin(url, next_url)
return True, next_url, request_options
class TokenPagination(RequestPagination):
def __init__(self, pagination):
self.fields = pagination.get("fields", ["next_page_token", "page_token"])
if not isinstance(self.fields, list) or len(self.fields) != 2:
raise QueryParseError("'pagination.fields' should be a list of 2 field names")
def next(self, url, request_options, response):
next_token = _apply_path_search(response, self.fields[0], "")
if not next_token:
return False, None, request_options
params = request_options.get("params", {})
# prevent infinite loop that can happen if self.fields[1] is wrong
if next_token == params.get(self.fields[1]):
raise Exception("{} did not change; possible misconfiguration".format(self.fields[0]))
params[self.fields[1]] = next_token
request_options["params"] = params
return True, url, request_options
register(JSON)View on GitHub (pinned to ca79fe988d)
Solutions
- Use a 2-element list: [response_field, request_param], e.g. ["next_cursor", "cursor"]
- Omit fields to use the defaults ["next_page_token", "page_token"]
- Confirm both names against the API's response body and accepted query parameters
Example fix
// before
{"pagination": {"type": "token", "fields": "next_cursor"}}
// after
{"pagination": {"type": "token", "fields": ["next_cursor", "cursor"]}} Defensive patterns
Strategy: validation
Validate before calling
fields = cfg.get('pagination', {}).get('fields', ['next_page_token', 'page_token'])
assert isinstance(fields, list) and len(fields) == 2 and all(isinstance(f, str) for f in fields) Type guard
def valid_fields(p: dict) -> bool:
f = p.get('fields', ['next_page_token', 'page_token'])
return isinstance(f, list) and len(f) == 2 and all(isinstance(x, str) for x in f) Prevention
- Document that fields = [response_field, request_param]
- Test the query once in the editor before scheduling
When it happens
Trigger: Setting pagination.fields to a string, a list of 1 or 3 items, or a dict, e.g. {"pagination": {"type": "token", "fields": "next_cursor"}}.
Common situations: Developer only specifies the response field and forgets the request param name, or copies field names from the API docs as a single string instead of a two-element list.
Related errors
- 'pagination.path' should be a string
- Unknown 'pagination.type' {}
- {} did not change; possible misconfiguration
- 'pagination' should be an object with a `type` property
- '{0}' is not a supported column type
AI-assisted analysis of getredash/redash@ca79fe988d (2026-08-28).
Data as JSON: /api/errors/b8737d14c7ccea8a.
Report an issue: GitHub.