Finding
The Subsonic createPlaylist / updatePlaylist endpoints accept repeated multi-value query parameters (songId, songIdToAdd, songIndexToRemove) that deserialize into Vec<String>. But axum 0.8's Query extractor uses serde_urlencoded 0.7.1, which cannot populate a Vec field from a query string at all. Every form fails: songId=x errors invalid type: string, expected a sequence; repeated keys songId=x&songId=y error identically; songId[]=x deserializes to None. So any real OpenSubsonic client that attaches songs to a playlist receives a 400 at query-parse and can never reach the handler.
Evidence
crates/paroche/src/subsonic/playlists.rs — the create_playlist / update_playlist handlers take Query<...> params with Vec<String> song fields. Confirmed empirically against serde_urlencoded 0.7.1 (axum 0.8 Query): no query-string shape populates the Vec. Surfaced while writing the #457 transaction-rollback tests — the song-insert loop is not drivable through the HTTP surface, so the create-path track-rollback could only be proven via a reachable sibling path.
Why this matters
Attaching songs to a playlist is core OpenSubsonic functionality. It is currently broken end-to-end for every client, independent of the transaction fix in #457 (which is correct-by-construction but only independently HTTP-testable on the metadata path).
Desired correction
Swap the query extractor for one that supports sequences — e.g. serde_html_form (a drop-in Query-shaped extractor that handles repeated keys) — across the Subsonic handlers that take repeated params. Audit the whole subsonic/ tree for other Vec-valued Query fields silently suffering the same fate.
Done when: createPlaylist/updatePlaylist with repeated songId/songIdToAdd actually attach the songs, proven by a test driving the real HTTP query surface (not a direct handler call); no Vec-valued Subsonic query param is left on the broken extractor.
Finding
The Subsonic
createPlaylist/updatePlaylistendpoints accept repeated multi-value query parameters (songId,songIdToAdd,songIndexToRemove) that deserialize intoVec<String>. But axum 0.8'sQueryextractor usesserde_urlencoded0.7.1, which cannot populate aVecfield from a query string at all. Every form fails:songId=xerrorsinvalid type: string, expected a sequence; repeated keyssongId=x&songId=yerror identically;songId[]=xdeserializes toNone. So any real OpenSubsonic client that attaches songs to a playlist receives a 400 at query-parse and can never reach the handler.Evidence
crates/paroche/src/subsonic/playlists.rs— thecreate_playlist/update_playlisthandlers takeQuery<...>params withVec<String>song fields. Confirmed empirically againstserde_urlencoded0.7.1 (axum 0.8Query): no query-string shape populates theVec. Surfaced while writing the #457 transaction-rollback tests — the song-insert loop is not drivable through the HTTP surface, so the create-path track-rollback could only be proven via a reachable sibling path.Why this matters
Attaching songs to a playlist is core OpenSubsonic functionality. It is currently broken end-to-end for every client, independent of the transaction fix in #457 (which is correct-by-construction but only independently HTTP-testable on the metadata path).
Desired correction
Swap the query extractor for one that supports sequences — e.g.
serde_html_form(a drop-inQuery-shaped extractor that handles repeated keys) — across the Subsonic handlers that take repeated params. Audit the wholesubsonic/tree for otherVec-valuedQueryfields silently suffering the same fate.Done when:
createPlaylist/updatePlaylistwith repeatedsongId/songIdToAddactually attach the songs, proven by a test driving the real HTTP query surface (not a direct handler call); noVec-valued Subsonic query param is left on the broken extractor.