fix(search): semantic toggle 400 (duplicate q) + unknown-author avatar 404 (LC-701) #667

Merged
longjacksonle merged 1 commit from fix/LC-701-semantic-search-errors into main 2026-08-10 20:57:48 +02:00

Fixes two errors surfaced when toggling the room-header "Semantic" search mode (LC-701). From the report's console: /search?room_id=1&semantic=1&q=&q=&q= returns 400, and /avatars/{id} returns 404. Bug fix only.

Root causes + fixes

  • Duplicate q -> 400: the Semantic checkbox used hx-include="[name='q']", a document-wide selector. A room page has several inputs named q (sidebar message search, people search, modal boxes), so toggling Semantic sent q=&q=&q=; axum's Query<SearchQuery> deserializes q into a scalar Option<String> and serde_urlencoded rejects duplicate keys with 400. Fixed by giving the room input id="lc-search-q-{room.id}" and scoping the checkbox's hx-include to that id, so exactly one q is sent. Keyword search was unaffected (the input includes only its own q).
  • Unknown-author avatar -> 404: GET /avatars/{id} 404'd for an id with no auth user (a bot author or a deleted user). LC-699 added an author avatar to each result row, so such a result rendered a broken image. This also violated the route's documented "always resolves to an image" invariant. Fixed by serving the generated default SVG for unknown ids. Regression test added (unknown_avatar_falls_back_to_default_image).

Tests

just test green (195 binaries, 1635 tests incl. the new avatar test), clippy clean under standalone + saas, cargo fmt --check clean. No DB migration, no i18n, no CSS; the keyword path, operator grammar, access gates, and the LC-699 presentation are untouched.

🤖 Generated with Claude Code

https://claude.ai/code/session_016ufqbuN7mjyt4ms5NEygMy

Fixes two errors surfaced when toggling the room-header "Semantic" search mode (LC-701). From the report's console: `/search?room_id=1&semantic=1&q=&q=&q=` returns 400, and `/avatars/{id}` returns 404. Bug fix only. ## Root causes + fixes - Duplicate `q` -> 400: the Semantic checkbox used `hx-include="[name='q']"`, a document-wide selector. A room page has several inputs named `q` (sidebar message search, people search, modal boxes), so toggling Semantic sent `q=&q=&q=`; axum's `Query<SearchQuery>` deserializes `q` into a scalar `Option<String>` and serde_urlencoded rejects duplicate keys with 400. Fixed by giving the room input `id="lc-search-q-{room.id}"` and scoping the checkbox's `hx-include` to that id, so exactly one `q` is sent. Keyword search was unaffected (the input includes only its own `q`). - Unknown-author avatar -> 404: `GET /avatars/{id}` 404'd for an id with no auth user (a bot author or a deleted user). LC-699 added an author avatar to each result row, so such a result rendered a broken image. This also violated the route's documented "always resolves to an image" invariant. Fixed by serving the generated default SVG for unknown ids. Regression test added (`unknown_avatar_falls_back_to_default_image`). ## Tests `just test` green (195 binaries, 1635 tests incl. the new avatar test), clippy clean under standalone + saas, `cargo fmt --check` clean. No DB migration, no i18n, no CSS; the keyword path, operator grammar, access gates, and the LC-699 presentation are untouched. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_016ufqbuN7mjyt4ms5NEygMy
fix(search): semantic toggle 400 (duplicate q) + unknown-author avatar 404 (LC-701)
All checks were successful
check-secrets / Nosey parker (push) Successful in 3s
check-secrets / TruffleHog (pull_request) Successful in 7s
check-secrets / Nosey parker (pull_request) Successful in 7s
check-secrets / Kingfisher (pull_request) Successful in 8s
Check / clippy + fmt + tests (pull_request) Successful in 5m27s
Create release / Create release from merged PR (pull_request) Has been skipped
check-secrets / Kingfisher (push) Successful in 5s
check-secrets / TruffleHog (push) Successful in 6s
a17c62ccd4
Two errors surfaced when toggling the room-header "Semantic" search mode.

Duplicate q -> 400: the Semantic checkbox used hx-include="[name='q']", a document-wide selector. A room page has several inputs named q (the sidebar message search, the people search, modal search boxes), so toggling Semantic sent q=&q=&q=. axum's Query<SearchQuery> deserializes q into a scalar Option<String>, and serde_urlencoded rejects duplicate keys with 400, so the popover errored instead of showing results. Fixed by giving the room-header input id="lc-search-q-{room.id}" and pointing the checkbox's hx-include at that id, so exactly one q is sent. Keyword search was unaffected because the text input includes only its own q.

Unknown-author avatar -> 404: GET /avatars/{id} did find_user_by_id(...).ok_or(NotFound), so an id with no auth user (a bot author or a since-deleted user) 404'd. LC-699 added an author avatar to each search result row, so a result from such a user rendered a broken img and logged console 404s. This also violated the route's own documented invariant that /avatars/{id} always resolves to an image (chat rows and the voice grid rely on it). Fixed by serving the generated default SVG for unknown ids instead of 404. Regression test added.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016ufqbuN7mjyt4ms5NEygMy
longjacksonle deleted branch fix/LC-701-semantic-search-errors 2026-08-10 20:57:48 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
psa-systems/lets-chat!667
No description provided.