{"record":{"id":"aa455d621929c361","repo":"getredash/redash","slug":"unknown-pagination-type","errorCode":null,"errorMessage":"Unknown 'pagination.type' {}","messagePattern":"Unknown 'pagination\\.type' (.+?)","errorType":"validation","errorClass":"QueryParseError","httpStatus":null,"severity":"error","filePath":"redash/query_runner/json_ds.py","lineNumber":244,"sourceCode":"    def next(self, url, request_options, response):\n        \"\"\"Checks the response for another page.\n\n        Returns:\n            has_more, next_url, next_request_options\n        \"\"\"\n        return False, None, request_options\n\n    @staticmethod\n    def from_config(configuration, pagination):\n        if not isinstance(pagination, dict) or not isinstance(pagination.get(\"type\"), str):\n            raise QueryParseError(\"'pagination' should be an object with a `type` property\")\n\n        if pagination[\"type\"] == \"url\":\n            return UrlPagination(pagination)\n        elif pagination[\"type\"] == \"token\":\n            return TokenPagination(pagination)\n\n        raise QueryParseError(\"Unknown 'pagination.type' {}\".format(pagination[\"type\"]))\n\n\nclass UrlPagination(RequestPagination):\n    def __init__(self, pagination):\n        self.path = pagination.get(\"path\", \"_links.next.href\")\n        if not isinstance(self.path, str):\n            raise QueryParseError(\"'pagination.path' should be a string\")\n\n    def next(self, url, request_options, response):\n        next_url = _apply_path_search(response, self.path, \"\")\n        if not next_url:\n            return False, None, request_options\n\n        next_url = urljoin(url, next_url)\n        return True, next_url, request_options\n\n\nclass TokenPagination(RequestPagination):","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/query_runner/json_ds.py#L226-L262","documentation":"Thrown by JSON data source pagination configuration parser when the 'pagination.type' field is neither 'url' nor 'token'. The JSON query runner only supports these two pagination strategies, and any other value aborts query parsing before any HTTP request is made.","triggerScenarios":"Setting pagination.type to anything other than \"url\" or \"token\" in the JSON query's pagination block, e.g. {\"pagination\": {\"type\": \"offset\", \"field\": \"page\"}}.","commonSituations":"Developer invents a pagination style the runner doesn't support (page numbers, offsets), copies a pagination config from a different tool, or misspells 'url'/'token' (e.g. 'Url', 'tokens').","solutions":["Set pagination.type to \"url\" (next-page URL extracted from response) or \"token\" (next-page token put in request params)","Remove the pagination block entirely if the endpoint returns everything in one response","Check spelling/casing of the type value"],"exampleFix":"// before\n{\"pagination\": {\"type\": \"offset\"}}\n// after\n{\"pagination\": {\"type\": \"url\", \"path\": \"_links.next.href\"}}","handlingStrategy":"validation","validationCode":"# before running the query\np = json.loads(query_text).get('pagination', {})\nif p and p.get('type') not in ('url', 'token'):\n    raise ValueError(\"pagination.type must be 'url' or 'token'\")","typeGuard":"def valid_pagination(cfg: dict) -> bool:\n    p = cfg.get('pagination')\n    return p is None or (isinstance(p, dict) and p.get('type') in ('url', 'token'))","tryCatchPattern":null,"preventionTips":["Validate the pagination block against the JSON DS schema before saving the query","Start from a working example query and only change endpoint/path fields"],"tags":["redash","json-datasource","pagination","config-validation"],"backgroundTag":"query-config-validation-failed","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}