Problem/Motivation
SearchApiAlgoliaBackend::search() and ::getAutocompleteSuggestions() build an $algolia_options array of Algolia search parameters and pass it to searchSingleIndex() as the third argument, requestOptions. None of those parameters reach Algolia.
In algoliasearch-client-php 4.x, requestOptions is the transport-level channel, not a container for search parameters. RequestOptions declares a $validOffsets allow-list of six names: headers, queryParameters, body, readTimeout, writeTimeout, connectTimeout. RequestOptionsFactory::normalize() copies every supplied key onto its skeleton, but create() then calls new RequestOptions($normalized) and that constructor only assigns from those six. Everything else is discarded, with no exception and no warning.
ApiWrapper::request() then builds the body as array_merge($data, $requestOptions->getBody()), where $data is searchParams and getBody() is empty. So POST /1/indexes/{indexName}/query receives only {"query": "..."}.
Dropped: attributesToRetrieve, facets, facetFilters, filters, numericFilters, length, offset, clickAnalytics, and analytics in autocomplete. So query conditions are not applied, facet counts are wrong, paging does not work, and no queryID is returned.
On indexes where attributesToRetrieve is set in the Algolia dashboard without search_api_id, this also surfaces as a warning for every hit:
Warning: Undefined array key "search_api_id" in Drupal\search_api_algolia\Plugin\search_api\backend\SearchApiAlgoliaBackend->search() (line 562 of modules/contrib/search_api_algolia/src/Plugin/search_api/backend/SearchApiAlgoliaBackend.php).
That warning is confirmed on 3.1.2; the other effects follow from the dropped parameters but were not each reproduced separately.
::deleteSplits() is unaffected: browseObjects() forwards its $requestOptions to SearchClient::browse() as the body.
Steps to reproduce
- Configure an Algolia server and index, and index some content.
- Set
attributesToRetrieveon the index in the Algolia dashboard to a list excludingsearch_api_id. - Index from the Search API index page. The warning appears there (screenshot attached).
Without step 2 there is no warning, but the parameters are still dropped. Log the outgoing request body to see it.
Proposed resolution
Move the search parameters into searchParams, which becomes the request body, in both methods. Patch attached. Confirmed on 3.1.2: with it applied the warning no longer appears.
Two side effects of the change:
disjunctiveFacets now has to be unset before the call. It is set by ::extractConditions() and read nowhere but the guard above the call. It is not among the 73 parameters SearchParamsObject defines, and the string appears nowhere in the client library. The existing guard is not enough on its own: it only fires when filters is also non-empty, and the two are populated by mutually exclusive branches, so a facet-only search leaves the key set. The patch adds an unconditional unset(). That makes the two existing blocks redundant; they are left in place to keep the diff minimal but can be deleted.
The error log in ::search() has to change. Assigning the query into $algolia_options removes $search, which the catch block referenced, so leaving it would raise Undefined variable $search from inside the error handler.
Remaining tasks
- Review the patch.
- Add coverage asserting the request body contains the search parameters. There is none today, which is why this went unnoticed.
- Decide whether to delete the redundant
disjunctiveFacetsblocks, and whether to drop the key from::extractConditions()entirely since nothing consumes it.
User interface changes
Search results, result counts, facet counts and paging will change on any site running this module, because filters and facets start being applied as intended.
API changes
None.
Data model changes
None.
| Comment | File | Size | Author |
|---|---|---|---|
| #3 | Screenshot 2026-08-07 at 1.06.14 PM.png | 46.55 KB | oscarclement |
| search-params-passed-as-request-options.patch | 1.84 KB | oscarclement |
Comments
Comment #2
oscarclement commentedComment #3
oscarclement commentedComment #4
oscarclement commentedComment #5
jlenni commentedThanks @oscarclement for the patch!
Tested with Search API Algolia 3.1.2 and Algolia PHP client 4.46.3.
The patch applies cleanly and fixes the issue for us.
Filters are passed correctly again and category/language filtering works as expected.
Request Body log example (from algolia backend):
{
"attributesToRetrieve": [
"search_api_id"
],
"facets": [
],
"clickAnalytics": true,
"length": 10,
"offset": 0,
"filters": "field_guide_gcat:1702 AND search_api_language:'de'",
"query": "*"
}
RTBC from my side 👍🏻
Comment #6
davps commented@oscarclement, thank you for the detailed breakdown of the issue and the attached solution.
The bug appeared after #3511165: Update the PHP API client to v4 . At the moment, it would be difficult to cover this case with tests, so they can be skipped for now. I've also tested it manually, and everything works as expected. Regarding the parameter — there is a separate issue #3381735: Unknown parameter: disjunctiveFacets for that, and we can handle it there.
Comment #9
davps commentedComment #11
davps commented