Skip to content

Commit 54ef165

Browse files
authored
Fix missing index exception handling (#126738)
* Fix missing index handling for partial-enabled queries
1 parent f4a6d18 commit 54ef165

File tree

5 files changed

+66
-47
lines changed

5 files changed

+66
-47
lines changed

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/CrossClusterQueryWithFiltersIT.java

+20-14
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99

1010
import org.elasticsearch.ElasticsearchException;
1111
import org.elasticsearch.client.internal.Client;
12+
import org.elasticsearch.cluster.RemoteException;
1213
import org.elasticsearch.common.Strings;
1314
import org.elasticsearch.common.settings.Settings;
15+
import org.elasticsearch.index.IndexNotFoundException;
1416
import org.elasticsearch.index.query.QueryBuilder;
1517
import org.elasticsearch.index.query.RangeQueryBuilder;
1618
import org.elasticsearch.test.transport.MockTransportService;
@@ -275,13 +277,13 @@ public void testFilterWithMissingIndex() {
275277
);
276278
assertThat(e.getDetailedMessage(), containsString("Unknown index [missing]"));
277279
// Local index missing + wildcards
278-
// FIXME: planner does not catch this now
279-
// e = expectThrows(VerificationException.class, () -> runQuery("from missing,logs*", randomBoolean(), filter).close());
280-
// assertThat(e.getDetailedMessage(), containsString("Unknown index [missing]"));
280+
// FIXME: planner does not catch this now, it should be VerificationException but for now it's runtime IndexNotFoundException
281+
var ie = expectThrows(IndexNotFoundException.class, () -> runQuery("from missing,logs*", randomBoolean(), filter).close());
282+
assertThat(ie.getDetailedMessage(), containsString("no such index [missing]"));
281283
// Local index missing + existing index
282-
// FIXME: planner does not catch this now
283-
// e = expectThrows(VerificationException.class, () -> runQuery("from missing,logs-1", randomBoolean(), filter).close());
284-
// assertThat(e.getDetailedMessage(), containsString("Unknown index [missing]"));
284+
// FIXME: planner does not catch this now, it should be VerificationException but for now it's runtime IndexNotFoundException
285+
ie = expectThrows(IndexNotFoundException.class, () -> runQuery("from missing,logs-1", randomBoolean(), filter).close());
286+
assertThat(ie.getDetailedMessage(), containsString("no such index [missing]"));
285287
// Local index missing + existing remote
286288
e = expectThrows(VerificationException.class, () -> runQuery("from missing,cluster-a:logs-2", randomBoolean(), filter).close());
287289
assertThat(e.getDetailedMessage(), containsString("Unknown index [missing]"));
@@ -318,15 +320,19 @@ public void testFilterWithMissingRemoteIndex() {
318320
);
319321
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
320322
// Local index missing + wildcards
321-
// FIXME: planner does not catch this now
322-
// e = expectThrows(VerificationException.class, () -> runQuery("from cluster-a:missing,cluster-a:logs*", randomBoolean(),
323-
// filter).close());
324-
// assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
323+
// FIXME: planner does not catch this now, it should be VerificationException but for now it's runtime RemoteException
324+
var ie = expectThrows(
325+
RemoteException.class,
326+
() -> runQuery("from cluster-a:missing,cluster-a:logs*", randomBoolean(), filter).close()
327+
);
328+
assertThat(ie.getDetailedMessage(), containsString("no such index [missing]"));
325329
// Local index missing + existing index
326-
// FIXME: planner does not catch this now
327-
// e = expectThrows(VerificationException.class, () -> runQuery("from cluster-a:missing,cluster-a:logs-2", randomBoolean(),
328-
// filter).close());
329-
// assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));
330+
// FIXME: planner does not catch this now, it should be VerificationException but for now it's runtime RemoteException
331+
ie = expectThrows(
332+
RemoteException.class,
333+
() -> runQuery("from cluster-a:missing,cluster-a:logs-2", randomBoolean(), filter).close()
334+
);
335+
assertThat(ie.getDetailedMessage(), containsString("no such index [missing]"));
330336
// Local index + missing remote
331337
e = expectThrows(VerificationException.class, () -> runQuery("from logs-1,cluster-a:missing", randomBoolean(), filter).close());
332338
assertThat(e.getDetailedMessage(), containsString("Unknown index [cluster-a:missing]"));

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/CrossClusterQueryWithPartialResultsIT.java

+28
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,34 @@ public void testOneRemoteClusterPartial() throws Exception {
161161
}
162162
}
163163

164+
public void testLocalIndexMissing() throws Exception {
165+
populateIndices();
166+
EsqlQueryRequest request = new EsqlQueryRequest();
167+
request.query("FROM ok-local,no_such_index | LIMIT 1");
168+
request.includeCCSMetadata(randomBoolean());
169+
for (boolean allowPartial : Set.of(true, false)) {
170+
request.allowPartialResults(allowPartial);
171+
Exception error = expectThrows(Exception.class, () -> runQuery(request).close());
172+
error = EsqlTestUtils.unwrapIfWrappedInRemoteException(error);
173+
assertThat(error.getMessage(), containsString("no such index"));
174+
assertThat(error.getMessage(), containsString("[no_such_index]"));
175+
}
176+
}
177+
178+
public void testRemoteIndexMissing() throws Exception {
179+
populateIndices();
180+
EsqlQueryRequest request = new EsqlQueryRequest();
181+
request.query("FROM cluster-a:ok-cluster1,cluster-a:no_such_index | LIMIT 1");
182+
request.includeCCSMetadata(randomBoolean());
183+
for (boolean allowPartial : Set.of(true, false)) {
184+
request.allowPartialResults(allowPartial);
185+
Exception error = expectThrows(Exception.class, () -> runQuery(request).close());
186+
error = EsqlTestUtils.unwrapIfWrappedInRemoteException(error);
187+
assertThat(error.getMessage(), containsString("no such index"));
188+
assertThat(error.getMessage(), containsString("[no_such_index]"));
189+
}
190+
}
191+
164192
public void testFailToReceiveClusterResponse() throws Exception {
165193
populateIndices();
166194
Exception simulatedFailure = randomFailure();

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/CrossClusterUsageTelemetryIT.java

-26
Original file line numberDiff line numberDiff line change
@@ -138,32 +138,6 @@ public void testFailed() throws Exception {
138138
assertThat(telemetry.getByRemoteCluster().size(), equalTo(0));
139139
}
140140

141-
// TODO: enable when skip-un patch is merged
142-
// public void testSkipAllRemotes() throws Exception {
143-
// var telemetry = getTelemetryFromQuery("from logs-*,c*:no_such_index | stats sum (v)", "unknown");
144-
//
145-
// assertThat(telemetry.getTotalCount(), equalTo(1L));
146-
// assertThat(telemetry.getSuccessCount(), equalTo(1L));
147-
// assertThat(telemetry.getFailureReasons().size(), equalTo(0));
148-
// assertThat(telemetry.getTook().count(), equalTo(1L));
149-
// assertThat(telemetry.getTookMrtFalse().count(), equalTo(0L));
150-
// assertThat(telemetry.getTookMrtTrue().count(), equalTo(0L));
151-
// assertThat(telemetry.getRemotesPerSearchAvg(), equalTo(2.0));
152-
// assertThat(telemetry.getRemotesPerSearchMax(), equalTo(2L));
153-
// assertThat(telemetry.getSearchCountWithSkippedRemotes(), equalTo(1L));
154-
// assertThat(telemetry.getClientCounts().size(), equalTo(0));
155-
//
156-
// var perCluster = telemetry.getByRemoteCluster();
157-
// assertThat(perCluster.size(), equalTo(3));
158-
// for (String clusterAlias : remoteClusterAlias()) {
159-
// var clusterData = perCluster.get(clusterAlias);
160-
// assertThat(clusterData.getCount(), equalTo(0L));
161-
// assertThat(clusterData.getSkippedCount(), equalTo(1L));
162-
// assertThat(clusterData.getTook().count(), equalTo(0L));
163-
// }
164-
// assertPerClusterCount(perCluster.get(LOCAL_CLUSTER), 1L);
165-
// }
166-
167141
public void testRemoteOnly() throws Exception {
168142
setupClusters();
169143
var telemetry = getTelemetryFromQuery("from c*:logs-* | stats sum (v)", "kibana");

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ClusterComputeHandler.java

+14-6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package org.elasticsearch.xpack.esql.plugin;
99

10+
import org.elasticsearch.ExceptionsHelper;
1011
import org.elasticsearch.action.ActionListener;
1112
import org.elasticsearch.action.ActionListenerResponseHandler;
1213
import org.elasticsearch.action.OriginalIndices;
@@ -16,6 +17,7 @@
1617
import org.elasticsearch.compute.operator.exchange.ExchangeSourceHandler;
1718
import org.elasticsearch.core.Releasable;
1819
import org.elasticsearch.core.TimeValue;
20+
import org.elasticsearch.index.IndexNotFoundException;
1921
import org.elasticsearch.tasks.CancellableTask;
2022
import org.elasticsearch.tasks.Task;
2123
import org.elasticsearch.tasks.TaskCancelledException;
@@ -88,12 +90,18 @@ void startComputeOnRemoteCluster(
8890
if (receivedResults == false && EsqlCCSUtils.shouldIgnoreRuntimeError(executionInfo, clusterAlias, e)) {
8991
EsqlCCSUtils.markClusterWithFinalStateAndNoShards(executionInfo, clusterAlias, EsqlExecutionInfo.Cluster.Status.SKIPPED, e);
9092
l.onResponse(DriverCompletionInfo.EMPTY);
91-
} else if (configuration.allowPartialResults()) {
92-
EsqlCCSUtils.markClusterWithFinalStateAndNoShards(executionInfo, clusterAlias, EsqlExecutionInfo.Cluster.Status.PARTIAL, e);
93-
l.onResponse(DriverCompletionInfo.EMPTY);
94-
} else {
95-
l.onFailure(e);
96-
}
93+
} else if (configuration.allowPartialResults()
94+
&& (ExceptionsHelper.unwrapCause(e) instanceof IndexNotFoundException) == false) {
95+
EsqlCCSUtils.markClusterWithFinalStateAndNoShards(
96+
executionInfo,
97+
clusterAlias,
98+
EsqlExecutionInfo.Cluster.Status.PARTIAL,
99+
e
100+
);
101+
l.onResponse(DriverCompletionInfo.EMPTY);
102+
} else {
103+
l.onFailure(e);
104+
}
97105
});
98106
ExchangeService.openExchange(
99107
transportService,

x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/plugin/ComputeService.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
package org.elasticsearch.xpack.esql.plugin;
99

10+
import org.elasticsearch.ExceptionsHelper;
1011
import org.elasticsearch.action.ActionListener;
1112
import org.elasticsearch.action.OriginalIndices;
1213
import org.elasticsearch.action.search.SearchRequest;
@@ -30,6 +31,7 @@
3031
import org.elasticsearch.core.Releasable;
3132
import org.elasticsearch.core.Releasables;
3233
import org.elasticsearch.core.Tuple;
34+
import org.elasticsearch.index.IndexNotFoundException;
3335
import org.elasticsearch.index.query.SearchExecutionContext;
3436
import org.elasticsearch.logging.LogManager;
3537
import org.elasticsearch.logging.Logger;
@@ -428,7 +430,8 @@ public void executePlan(
428430
);
429431
dataNodesListener.onResponse(r.getCompletionInfo());
430432
}, e -> {
431-
if (configuration.allowPartialResults()) {
433+
if (configuration.allowPartialResults()
434+
&& (ExceptionsHelper.unwrapCause(e) instanceof IndexNotFoundException) == false) {
432435
execInfo.swapCluster(
433436
LOCAL_CLUSTER,
434437
(k, v) -> new EsqlExecutionInfo.Cluster.Builder(v).setStatus(

0 commit comments

Comments
 (0)