From 45f3971d004e9ae2d8322e996b446a87a6ec91fa Mon Sep 17 00:00:00 2001 From: Pete Gillin Date: Wed, 29 Oct 2025 10:12:21 +0000 Subject: [PATCH] Reindex-from-remote: Fail on manual slicing param (#137275) When the `_reindex` API is used with a remote source (`source.remote` is set in the request body), neither manual slicing (via `source.slice` in the request body) nor automatic slicing (via the `slices` URL parameter) are supported. Prior to this change, on sending a request with a remote source and manual slicing enabled, the manual slicing specification would be ignored, and the complete source would be reindexed without slicing. After this change, the API will return a response with an HTTP code 400 (Bad Request) instead. The new behaviour more correctly indicates to the user that the requested functionality is not available, rather than silently ignoring part of their request. Note that: - Prior to this change, sending a request with a remote source and *automatic* slicing enabled already resulted in the correct 400 response. - The [docs](https://www.elastic.co/docs/reference/elasticsearch/rest-apis/reindex-indices#docs-reindex-slice) already correctly stated "Reindexing from remote clusters does not support manual or automatic slicing." - As a drive-by, this change also adds a unit test for the validation with the `slices` parameter set to `auto`. (Previously, only the case where it was set to a number greater than 1 was tested.) Closes #136269 --- docs/changelog/137275.yaml | 6 ++ .../index/reindex/ReindexRequest.java | 6 ++ .../index/reindex/ReindexRequestTests.java | 57 ++++++++++++++++++- 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 docs/changelog/137275.yaml diff --git a/docs/changelog/137275.yaml b/docs/changelog/137275.yaml new file mode 100644 index 0000000000000..d39b968d358e2 --- /dev/null +++ b/docs/changelog/137275.yaml @@ -0,0 +1,6 @@ +pr: 137275 +summary: "Reindex-from-remote: Fail on manual slicing param" +area: Indices APIs +type: bug +issues: + - 136269 diff --git a/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java b/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java index 24fc46bb88792..edce26e55dfd1 100644 --- a/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java +++ b/server/src/main/java/org/elasticsearch/index/reindex/ReindexRequest.java @@ -115,6 +115,12 @@ public ActionRequestValidationException validate() { if (getSlices() == AbstractBulkByScrollRequest.AUTO_SLICES || getSlices() > 1) { e = addValidationError("reindex from remote sources doesn't support slices > 1 but was [" + getSlices() + "]", e); } + if (getSearchRequest().source().slice() != null) { + e = addValidationError( + "reindex from remote sources doesn't support source.slice but was [" + getSearchRequest().source().slice() + "]", + e + ); + } if (getRemoteInfo().getUsername() != null && getRemoteInfo().getPassword() == null) { e = addValidationError("reindex from remote source included username but not password", e); } diff --git a/server/src/test/java/org/elasticsearch/index/reindex/ReindexRequestTests.java b/server/src/test/java/org/elasticsearch/index/reindex/ReindexRequestTests.java index 2204a0bb3b2b0..44f867124be39 100644 --- a/server/src/test/java/org/elasticsearch/index/reindex/ReindexRequestTests.java +++ b/server/src/test/java/org/elasticsearch/index/reindex/ReindexRequestTests.java @@ -162,7 +162,7 @@ public void testReindexFromRemoteDoesNotSupportSearchQuery() { ); } - public void testReindexFromRemoteDoesNotSupportSlices() { + public void testReindexFromRemoteDoesNotSupportSlicesParameterGreaterThan1() { ReindexRequest reindex = newRequest(); reindex.setRemoteInfo( new RemoteInfo( @@ -178,6 +178,7 @@ public void testReindexFromRemoteDoesNotSupportSlices() { RemoteInfo.DEFAULT_CONNECT_TIMEOUT ) ); + // Enable automatic slicing with a random number of slices greater than 1 (like setting the slices URL parameter): reindex.setSlices(between(2, Integer.MAX_VALUE)); ActionRequestValidationException e = reindex.validate(); assertEquals( @@ -186,6 +187,60 @@ public void testReindexFromRemoteDoesNotSupportSlices() { ); } + public void testReindexFromRemoteDoesNotSupportSlicesParameterSetToAuto() { + ReindexRequest reindex = newRequest(); + reindex.setRemoteInfo( + new RemoteInfo( + randomAlphaOfLength(5), + randomAlphaOfLength(5), + between(1, Integer.MAX_VALUE), + null, + matchAll, + null, + null, + emptyMap(), + RemoteInfo.DEFAULT_SOCKET_TIMEOUT, + RemoteInfo.DEFAULT_CONNECT_TIMEOUT + ) + ); + // Enable automatic slicing with an automatically chosen number of slices (like setting the slices URL parameter to "auto"): + reindex.setSlices(AbstractBulkByScrollRequest.AUTO_SLICES); + ActionRequestValidationException e = reindex.validate(); + assertEquals( + "Validation Failed: 1: reindex from remote sources doesn't support slices > 1 but was [" + reindex.getSlices() + "];", + e.getMessage() + ); + } + + public void testReindexFromRemoteDoesNotSupportSlicesSourceField() { + ReindexRequest reindex = newRequest(); + reindex.setRemoteInfo( + new RemoteInfo( + randomAlphaOfLength(5), + randomAlphaOfLength(5), + between(1, Integer.MAX_VALUE), + null, + matchAll, + null, + null, + emptyMap(), + RemoteInfo.DEFAULT_SOCKET_TIMEOUT, + RemoteInfo.DEFAULT_CONNECT_TIMEOUT + ) + ); + // Enable manual slicing (like setting source.slice.max and source.slice.id in the request body): + int numSlices = randomIntBetween(2, Integer.MAX_VALUE); + int sliceId = randomIntBetween(0, numSlices - 1); + reindex.getSearchRequest().source().slice(new SliceBuilder(sliceId, numSlices)); + ActionRequestValidationException e = reindex.validate(); + assertEquals( + "Validation Failed: 1: reindex from remote sources doesn't support source.slice but was [" + + reindex.getSearchRequest().source().slice() + + "];", + e.getMessage() + ); + } + public void testReindexFromRemoteRejectsUsernameWithNoPassword() { ReindexRequest reindex = newRequest(); reindex.setRemoteInfo(