Issue Description
With Meilisearch as the search store, ContactCard/query returns total: 0 when it sorts by created or updated and has no filter. The same query without the sort returns every card. The same sort with any filter also returns the correct cards.
Cause (v0.16.23, same on main 23f76bd): contact/query.rs turns a created/updated sort into a local SortedSet comparator. SearchQuery::with_account_id adds one SearchFilter::Operator(AccountId). In SearchStore::query_account (store/src/dispatch/search.rs), the AccountId operator does not set has_external_filters. The comparator is local, so the query skips the mask shortcut and the external branch. The filters then reach the local SearchQuery::filter() (store/src/search/local.rs). That loop skips the Operator with continue, so state.bm stays None, and unwrap_or_default() returns an empty bitmap.
Suggested fix: strip the AccountId operator before the local merge, or use query.mask when no other filter remains.
Expected Behavior
An unfiltered ContactCard/query sorted by created or updated returns every card in the account, in that order.
Actual Behavior
It returns ids: and total: 0. Clients that list an address book in a stable order show it as empty. Example: @bryanberger/jmap-mcp contacts_search with no criteria.
Reproduction Steps
- Use Meilisearch as the search store, and have an account with contact cards (510 here).
- Send:
[“ContactCard/query”, {“accountId”: “c”, “calculateTotal”: true,
“sort”: [{“property”: “created”, “isAscending”: true}]}, “0”] - Result: total 0.
Results on the same account:
- no filter, no sort: 510
- no filter, sort created asc or desc: 0
- no filter, sort updated: 0
- inAddressBook “b”, sort created: 508
- email “gmail”, sort created: 79
This is not a stale index. The unsorted query and the filtered sorted queries return the full set.
Relevant Log Output
Nothing is logged. The query succeeds, but it returns 0 results.
Stalwart Version
v0.16.x
Installation Method
Binary (Linux)
Database Backend
FoundationDB
Blob Storage
S3-compatible
Search Engine
Meilisearch
Directory Backend
Internal
Additional Context
The internal FTS store takes the internal_fts() path, so it is probably not affected. I did not test it. Redis Cluster is the in-memory store and NATS is the coordinator; neither should matter here. I checked the forum and GitHub for duplicates and found none.
I have reviewed the documentation and FAQ and confirm that my issue is NOT addressed there.
on
I have searched this support forum (open and closed topics) and confirm this is not a duplicate.
on
I understand that topics in this category are triaged by a bot first but a human reply will follow up. If I’d prefer a human-only reply, I’ll add the no-ai tag to my topic.
on