The browse-on-click blank sentinel was trimmed to empty (correct), but
the typed query had already been bound unconditionally — the id-source
suggestion query has no score CASE to reference it, leaving an unused
parameter Postgres rejects (42P18). Every click of an empty library /
collection / added-by box answered 'No matching values' via the error
path.
- ComposedFieldValues binds the typed query ONLY in branches that
reference it and only when non-blank; the score expression is
'0 AS score' for browse (no param) and the similarity CASE when
typing. composedIDSourceValues takes the raw typed string and binds
it only when the name filter is built. userBind already followed
this discipline; audited every bind site in the file (fuzzy helpers,
composed search, count) — all interpolate immediately.
- Tests: library browse under rules (exactly the surviving library,
count pinned), series browse blank, added_by browse blank (no
error), collection browse blank (offered with count) and under a
zero-match rule (never offered). Verified end-to-end against the
live dev data: author+Sapkowski AND narrator+Kenny → Audiobooks (8).