Surface the real cause of internal PIT failures instead of an opaque message#5631
Draft
ahkcs wants to merge 1 commit into
Draft
Surface the real cause of internal PIT failures instead of an opaque message#5631ahkcs wants to merge 1 commit into
ahkcs wants to merge 1 commit into
Conversation
…message Internal PIT creation/deletion failures were reported to callers as the generic "Error occurred while creating PIT for internal plugin operation" with no root cause, and a security denial was only recognized when it was the direct cause of the ExecutionException. On a multi-node domain the CreatePit shard action runs remotely, so a permission denial comes back wrapped (e.g. RemoteTransportException -> OpenSearchSecurityException). The single-level instanceof check missed the wrapped case and flattened the 403 into the opaque message, hiding both the missing permission and any non-permission failure (e.g. PIT context exhaustion) behind the same string. Walk the full cause+suppressed chain with ExceptionsHelper: rethrow a recovered OpenSearchSecurityException as-is so the caller still gets a 403, and otherwise include the root cause in the message so the surfaced error is diagnostic. Applied to both the Calcite path (OpenSearchNodeClient) and the legacy path (PointInTimeHandlerImpl), which shared the same latent bug (its catch (OpenSearchSecurityException) was dead code since Future.get() always wraps in ExecutionException). Also re-set the interrupt flag on InterruptedException. Tests: unit tests cover the direct, transport-wrapped, and non-security cases. A PPLPermissionsIT case forces the PIT path on a tiny dataset via index.max_result_window=1, verifying a user without PIT permission gets a clean 403 (not the opaque message) and that granting the permission lets the query succeed. Signed-off-by: Kai Huang <ahkcs@amazon.com>
ahkcs
requested review from
LantaoJin,
RyanL1997,
Swiddis,
acarbonetto,
anirudha,
dai-chen,
joshuali925,
mengweieric,
noCharger,
penghuo,
ps48,
qianheng-aws,
songkant-aws,
vamsimanohar,
ykmr1224 and
yuancu
as code owners
July 16, 2026 21:33
Contributor
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
Contributor
PR Code Suggestions ✨Explore these optional code suggestions:
|
ahkcs
marked this pull request as draft
July 16, 2026 21:40
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Internal Point-in-Time (PIT) creation/deletion failures were surfaced to callers as the opaque, cause-less message
Error occurred while creating PIT for internal plugin operation, and a permission denial was only recognized when theOpenSearchSecurityExceptionwas the direct cause of theExecutionException.On a multi-node domain the
CreatePitshard action runs remotely, so a denial comes back wrapped (e.g.RemoteTransportException -> OpenSearchSecurityException). The single-levelinstanceofcheck missed that wrapped case and flattened the 403 into the generic string — hiding both the missing permission and any non-permission failure (e.g. PIT-context exhaustion, circuit breaker) behind one indistinguishable message. This made a customer-reported failure on the Statistics/PPL path effectively undiagnosable from the error alone.This is a diagnostics/robustness fix, not a behavior change to PIT itself:
ExceptionsHelper.unwrapCausesAndSuppressed. If anOpenSearchSecurityExceptionis anywhere in the chain, rethrow it as-is so the caller still receives a clean 403.ExceptionsHelper.unwrapCause) in the message, so a non-permission failure is diagnostic instead of opaque.OpenSearchNodeClientPointInTimeHandlerImpl, whosecatch (OpenSearchSecurityException)was dead code (Future.get()always wraps inExecutionException, so the security exception was never the top-level type caught).InterruptedException.Why "always use PIT" isn't touched: rather than change production routing, the new IT lowers
index.max_result_windowto1on a 2-doc index, which forces any ordinary query down the PIT path. This lets us exercise the PIT permission failure on a tiny dataset instead of the fidelity-scale volume that triggers it in production.Scope / honesty note
This change makes the error legible; it is not itself the cure for the reported incident. If the customer's failure is a wrapped permission denial, this surfaces the clean 403 (and the remediation is granting
indices:data/read/point_in_time/{create,delete}). If it is instead a resource failure at peak, this now puts the real root cause in the message so it can be diagnosed. Determining which requires the raw stack trace from the affected domain.Testing
Unit (
OpenSearchNodeClientTest,PointInTimeHandlerImplTest):OpenSearchSecurityException→ rethrown as 403OpenSearchSecurityException(the multi-node case) → still rethrown as 403 (previously flattened)Integration (
PPLPermissionsIT, security cluster):testForcedPitQueryWithoutPitPermissionReturnsCleanForbidden— query forced through PIT; user without PIT permission gets a clean 403 naming the permission, and not the opaque generic message.testForcedPitQueryWithPitPermissionSucceeds— granting the two PIT permissions lets the same query succeed (the remediation).All new and existing tests in the touched classes pass;
spotlessJavaCheckis clean on:opensearch,:legacy,:integ-test.Known follow-ups (out of scope)
OpenSearchRestClient.createPithas the same single-level unwrap pattern and should get the same treatment.BackgroundSearchScannershares the pattern but its direct-cause handling is load-bearing for theafterKey == EMPTYcase — left untouched here.Check List
--signoffor-s.By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.