Skip to content

Bug - Repeated query parameters are collapsed to a single value when proxied #109

Description

@zosiaboj

Description of the bug

When a client sends a request through starrproxy with a repeated query parameter (e.g. ?trackFileIds=1&trackFileIds=2&trackFileIds=3), only one of the values reaches the upstream *arr instance — the rest are silently dropped. The proxied request returns HTTP 200 with a well-formed response, so nothing about the failure is visible to the client; it just gets far less data than it asked for.

This looks like the query string is being parsed into a single-value map (map[string]string) somewhere in the proxy's request-forwarding path, rather than a multi-value structure (map[string][]string / url.Values in Go), so each repeated key overwrites the previous one and only the last survives.

Confirmed against Lidarr's /api/v1/trackfile endpoint, but the bug is in how the proxy handles the query string generally, so it likely affects any repeated-parameter query against any of the proxied *arr APIs (Sonarr, Radarr, Readarr, etc.), not just this one endpoint.

Expected behavior

Both requests below should return the same 11 TrackFile objects — starrproxy should forward all values of a repeated query parameter to the upstream instance unchanged.

Steps to reproduce

  1. Pick a set of valid IDs that a bulk endpoint accepts as a repeated parameter — e.g. 11 trackFileIds for tracks in one Lidarr album.
  2. Send the request directly to Lidarr, bypassing starrproxy:
    GET http://<lidarr-host>:8686/api/v1/trackfile?trackFileIds=506446&trackFileIds=506559&trackFileIds=506622&trackFileIds=506688&trackFileIds=506757&trackFileIds=506806&trackFileIds=506852&trackFileIds=506896&trackFileIds=506937&trackFileIds=506975&trackFileIds=507008
    X-Api-Key: <real lidarr key>
    
    Returns all 11 matching TrackFile objects.
  3. Send the exact same query string, same API key scope, through starrproxy:
    GET http://starrproxy/api/v1/trackfile?trackFileIds=506446&trackFileIds=506559&trackFileIds=506622&trackFileIds=506688&trackFileIds=506757&trackFileIds=506806&trackFileIds=506852&trackFileIds=506896&trackFileIds=506937&trackFileIds=506975&trackFileIds=507008
    X-Api-Key: <starrproxy-scoped key>
    
    Returns only 1 object — the one matching the last trackFileIds value in the query string (507008 in this example). Status is 200; there is no error, warning, or indication that 10 of the 11 requested items were dropped.

Starr Proxy Version

main (branch main, commit abfb380, image ghcr.io/notifiarr/starrproxy:main)

Deployment

Docker

Relevant log output

(none — the request completes normally with a 200 and no error/warning is logged; that's part of the problem)

Additional context

  • Lidarr version: 3.1.4.5029, nightly branch (package nightly-4a6e95e by hotio)
  • Single-value query params (e.g. ?albumId=X) work correctly through the proxy — only repeated keys are affected.
  • Impact: this silently broke bulk data fetching in a third-party app (Aurral, github.com/lklynet/aurral) using starrproxy for scoped Lidarr access — its library-sync feature calls this endpoint in batches of up to 400 track-file IDs and, because of this bug, only ever got 1 file back per batch. Because the request succeeds with a 200 and a normally-shaped JSON array, the failure was completely silent from the client's side and took a while to track down.
  • Suggested fix: if the request forwarding is implemented in Go, this is consistent with parsing the incoming query string into a map[string]string rather than using net/url's url.Values (a map[string][]string) and its Encode()/RawQuery handling, which preserves repeated keys correctly end-to-end. Re-serialising the parsed query with url.Values.Encode() when building the upstream request should fix this without needing endpoint-specific handling.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions