Description
Elasticsearch Version
8.19
Installed Plugins
No response
Java Version
bundled
OS Version
Linux
Problem Description
When the conditions are met for the new feature Batched query execution (#121885) to be applied, the specific use case where executing a request within a point in time with alias filters leads to a NPE.
In SearchQueryThenFetchAsyncAction
#isPartOfPIT
, a null
namedWriteableRegistry is passed when trying to access the search context id of the point in time builder. Since the alias filters use the registry when decoding the pit ID, this results in a NPE.
Steps to Reproduce
Reproduced with:
- a simple cluster using
docker.elastic.co/elasticsearch/elasticsearch:8.19.0-SNAPSHOT
with two data nodes - a bash script which executes a search within a pit opened on an index alias (see script bellow)
=> the script hangs on the search request, due to the NPE on AliasFilter
::readFrom
during the batched executions on the data nodes.
...
==> Opening a PIT with index alias...
==> Searching with PIT...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1371 0 0 100 1371 0 20 0:01:08 0:01:08 --:--:-- 0
The script works as expected when the pit is opened directly on the index, rather then on the index alias.
Script:
#!/bin/bash
echo "==> Creating an index..."
curl -X PUT "localhost:9200/index1" -H 'Content-Type: application/json' -d '{
"settings": { "number_of_shards": 10, "number_of_replicas": 0 }
}' > /dev/null
echo "==> Creating an index alias..."
curl -X POST "localhost:9200/_aliases" -H 'Content-Type: application/json' -d '{
"actions": [
{ "add": { "index": "index1", "alias": "alias1", "filter": { "term": { "tag": "a" } } } }
]
}' > /dev/null
echo "==> Inserting documents..."
for i in $(seq 1 1000); do
TAG=$([ $((RANDOM % 2)) -eq 0 ] && echo "a" || echo "b")
curl -s -X POST "localhost:9200/index1/_doc" -H 'Content-Type: application/json' -d "{
\"id\": \"$i\", \"tag\": \"$TAG\"
}" > /dev/null
done
echo "Forcing refresh..."
curl -s -X POST "localhost:9200/index1/_refresh" > /dev/null
echo "==> Opening a PIT with index alias..."
PIT_ID=$(curl -s -X POST "localhost:9200/alias1/_pit?keep_alive=1m" -H 'Content-Type: application/json' | jq -r '.id')
echo "==> Searching with PIT..."
SEARCH_RESULT=$(curl -X POST "localhost:9200/_search" -H 'Content-Type: application/json' -d "{
\"pit\": {
\"id\": \"${PIT_ID}\",
\"keep_alive\": \"1m\"
},
\"size\": 0,
\"query\": {
\"match_all\": {}
}
}")
HITS_COUNT=$(echo "$SEARCH_RESULT" | jq '.hits.total.value')
echo " ==> Count: $HITS_COUNT"
echo "==> Closing the PIT..."
curl -s -X DELETE "localhost:9200/_pit" -H 'Content-Type: application/json' -d "{
\"id\": \"$PIT_ID\"
}" > /dev/null
echo "==> Deleting index..."
curl -s -X DELETE "localhost:9200/index1" > /dev/null
Logs (if relevant)
java.lang.NullPointerException: Cannot invoke "org.elasticsearch.common.io.stream.NamedWriteableRegistry.getReader(java.lang.Class, String)" because "this.namedWriteableRegistry" is null
org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput,readNamedWriteable,NamedWriteableAwareStreamInput.java,56,1
org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput,readNamedWriteable,NamedWriteableAwareStreamInput.java,33,1
org.elasticsearch.common.io.stream.StreamInput,readOptionalNamedWriteable,StreamInput.java,1178,1
org.elasticsearch.search.internal.AliasFilter,readFrom,AliasFilter.java,48,1
org.elasticsearch.common.io.stream.StreamInput,readImmutableMap,StreamInput.java,811,1
org.elasticsearch.common.io.stream.StreamInput,readImmutableMap,StreamInput.java,796,1
org.elasticsearch.action.search.SearchContextId,decode,SearchContextId.java,102,1
org.elasticsearch.search.builder.PointInTimeBuilder,getSearchContextId,PointInTimeBuilder.java,113,1
org.elasticsearch.action.search.SearchQueryThenFetchAsyncAction,isPartOfPIT,SearchQueryThenFetchAsyncAction.java,396,1