{"record":{"id":"8eed3b6574681c7d","repo":"getredash/redash","slug":"only-get-or-post-methods-are-allowed","errorCode":null,"errorMessage":"Only GET or POST methods are allowed.","messagePattern":"Only GET or POST methods are allowed\\.","errorType":"validation","errorClass":"QueryParseError","httpStatus":null,"severity":"warning","filePath":"redash/query_runner/json_ds.py","lineNumber":192,"sourceCode":"\n        method = query.get(\"method\", \"get\")\n        request_options = project(query, (\"params\", \"headers\", \"data\", \"auth\", \"json\", \"verify\"))\n\n        fields = query.get(\"fields\")\n        path = query.get(\"path\")\n\n        if \"pagination\" in query:\n            pagination = RequestPagination.from_config(self.configuration, query[\"pagination\"])\n        else:\n            pagination = None\n\n        if isinstance(request_options.get(\"auth\", None), list):\n            request_options[\"auth\"] = tuple(request_options[\"auth\"])\n        elif self.configuration.get(\"username\") or self.configuration.get(\"password\"):\n            request_options[\"auth\"] = (self.configuration.get(\"username\"), self.configuration.get(\"password\"))\n\n        if method not in (\"get\", \"post\"):\n            raise QueryParseError(\"Only GET or POST methods are allowed.\")\n\n        if fields and not isinstance(fields, list):\n            raise QueryParseError(\"'fields' needs to be a list.\")\n\n        results, error = self._get_all_results(query[\"url\"], method, path, pagination, **request_options)\n        return parse_json(results, fields), error\n\n    def _get_all_results(self, url, method, result_path, pagination, **request_options):\n        \"\"\"Get all results from a paginated endpoint.\"\"\"\n        base_url = self.configuration.get(\"base_url\")\n        url = urljoin(base_url, url)\n\n        results = []\n        has_more = True\n        while has_more:\n            response, error = self._get_json_response(url, method, **request_options)\n            has_more = False\n","sourceCodeStart":174,"sourceCodeEnd":210,"githubUrl":"https://github.com/getredash/redash/blob/ca79fe988d81cdac9675b412f3dfcab107bc1fbc/redash/query_runner/json_ds.py#L174-L210","documentation":"The JSON URL runner supports only GET and POST requests. method defaults to 'get'; any other value (put, delete, patch, or a typo like 'GET ' with whitespace/caps) fails the `method not in ('get','post')` check and raises QueryParseError.","triggerScenarios":"Setting method: put / method: delete / method: patch in the query YAML, or a capitalized/whitespace variant like 'Get' that doesn't match the lowercase tuple.","commonSituations":"Trying REST APIs that require PUT/DELETE, or copying curl examples that use those verbs.","solutions":["Change method to get or post (omit the key entirely for GET)","If the API needs PUT/DELETE, proxy the call or use the Python query runner to make the request"],"exampleFix":"# before\nmethod: put\n# after\nmethod: post","handlingStrategy":"validation","validationCode":"def method_is_supported(q: dict) -> bool:\n    return q.get(\"method\", \"get\").lower() in (\"get\", \"post\")","typeGuard":"def is_valid_json_ds_query(q: str) -> bool:\n    try:\n        parsed = yaml.safe_load(q)\n    except yaml.YAMLError:\n        return False\n    if not isinstance(parsed, dict) or \"url\" not in parsed:\n        return False\n    return str(parsed.get(\"method\", \"get\")).lower() in (\"get\", \"post\")","tryCatchPattern":null,"preventionTips":["Use only get/post (lowercase, no whitespace)","Omit method for GET requests","Route PUT/DELETE needs through a proxy or the Python runner"],"tags":["json-ds","http-method","query-validation"],"backgroundTag":"unsupported-http-method","analyzedSha":"ca79fe988d81cdac9675b412f3dfcab107bc1fbc","analyzedAt":"2026-08-28T18:32:34.637Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}