jdx/mise · error

unsupported query parameter

Error message

unsupported query parameter

What it means

For non-git requests, `authorize` parses the query string and permits only the keys `ref`, `page`, and `per_page`. Any other query parameter causes the request to be rejected, because the relay forwards only narrowly defined query shapes and must not pass arbitrary parameters upstream. Git smart-HTTP requests are exempt from this check.

Solutions

  1. Remove all query parameters except `ref`, `page`, and `per_page` from the request URL
  2. If you need server-side filtering/sorting not supported by these keys, fetch unfiltered and filter client-side
  3. Move any credentials out of query strings into headers handled by the relay

Example fix

// before
GET /api/repos/org/repo/contents?ref=main&sort=name
// after
GET /api/repos/org/repo/contents?ref=main
Defensive patterns

Strategy: validation

Validate before calling

fn query_is_allowed(query: Option<&str>) -> bool {
    query.map_or(true, |q| {
        url::form_urlencoded::parse(q.as_bytes())
            .all(|(k, _)| matches!(k.as_ref(), "ref" | "page" | "per_page"))
    })
}

Try / catch

match authorize(&scope, method, path, query) {
    Err(e) if e.to_string().contains("unsupported query parameter") => {
        eprintln!("strip non-allowlisted query params (only ref, page, per_page)");
    }
    Ok(t) => forward(t),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A client appends extra parameters to an API request, e.g. `/api/repos/o/r/contents?ref=main&token=x`, `?sort=name`, `?recursive=true`, or a cache-busting `?_=1234` on a web archive download.

Common situations: SDKs or HTTP clients that automatically add parameters (utm, cache-busters, auth tokens in query strings); tools passing sort/order/filter options the relay does not allowlist; leaked credentials embedded in query strings by misconfigured clients.

Understand the failure class

Background: "Invalid query parameter" / "Failed to parse value of ...": fixing bad query string parameters across APIs — this error's family across 36 libraries.

Related errors


AI-assisted analysis of jdx/mise@533346cc37 (2026-09-17). Data as JSON: /api/errors/8ca7c72f53894ceb. Report an issue: GitHub.

Appendix: source

Thrown at src/github_relay.rs:234

            matches!(*kind, "refs" | "matching-refs") && matches!(method, "GET" | "HEAD")
        }
        ["api", "repos", _, _, kind, ..] => {
            matches!(
                *kind,
                "contents" | "releases" | "tags" | "branches" | "tarball" | "zipball"
            ) && matches!(method, "GET" | "HEAD")
        }
        ["web", _, _, "releases", "download", _, ..] => matches!(method, "GET" | "HEAD"),
        ["web", _, _, "archive", _, ..] => matches!(method, "GET" | "HEAD"),
        _ => false,
    };
    if !allowed {
        bail!("GitHub relay permits read-only repository operations only");
    }
    if !git && let Some(query) = query {
        for (key, _) in url::form_urlencoded::parse(query.as_bytes()) {
            if !matches!(key.as_ref(), "ref" | "page" | "per_page") {
                bail!("unsupported query parameter");
            }
        }
    }
    let host = if p[0] == "api" {
        "api.github.com"
    } else {
        "github.com"
    };
    let suffix = path.split_once('/').expect("validated path").1;
    let mut url = format!("https://{host}/{suffix}");
    let archive_repo = match p.as_slice() {
        ["api", "repos", _, _, "tarball" | "zipball", ..] => Some(name.clone()),
        ["web", _, _, "archive", rest @ ..] => {
            let reference = rest.join("/");
            let (kind, reference) = if let Some(reference) = reference.strip_suffix(".tar.gz") {
                ("tarball", reference)
            } else if let Some(reference) = reference.strip_suffix(".zip") {
                ("zipball", reference)

View on GitHub (pinned to 533346cc37)