getredash/redash · warning · QueryParseError

Only GET or POST methods are allowed.

Error message

Only GET or POST methods are allowed.

What it means

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.

Source

Thrown at redash/query_runner/json_ds.py:192

        method = query.get("method", "get")
        request_options = project(query, ("params", "headers", "data", "auth", "json", "verify"))

        fields = query.get("fields")
        path = query.get("path")

        if "pagination" in query:
            pagination = RequestPagination.from_config(self.configuration, query["pagination"])
        else:
            pagination = None

        if isinstance(request_options.get("auth", None), list):
            request_options["auth"] = tuple(request_options["auth"])
        elif self.configuration.get("username") or self.configuration.get("password"):
            request_options["auth"] = (self.configuration.get("username"), self.configuration.get("password"))

        if method not in ("get", "post"):
            raise QueryParseError("Only GET or POST methods are allowed.")

        if fields and not isinstance(fields, list):
            raise QueryParseError("'fields' needs to be a list.")

        results, error = self._get_all_results(query["url"], method, path, pagination, **request_options)
        return parse_json(results, fields), error

    def _get_all_results(self, url, method, result_path, pagination, **request_options):
        """Get all results from a paginated endpoint."""
        base_url = self.configuration.get("base_url")
        url = urljoin(base_url, url)

        results = []
        has_more = True
        while has_more:
            response, error = self._get_json_response(url, method, **request_options)
            has_more = False

View on GitHub (pinned to ca79fe988d)

Solutions

  1. Change method to get or post (omit the key entirely for GET)
  2. If the API needs PUT/DELETE, proxy the call or use the Python query runner to make the request

Example fix

# before
method: put
# after
method: post
Defensive patterns

Strategy: validation

Validate before calling

def method_is_supported(q: dict) -> bool:
    return q.get("method", "get").lower() in ("get", "post")

Type guard

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
    return str(parsed.get("method", "get")).lower() in ("get", "post")

Prevention

When it happens

Trigger: 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.

Common situations: Trying REST APIs that require PUT/DELETE, or copying curl examples that use those verbs.

Related errors


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