Skip to content

Allow action prefixes to be registered from plugins#20913

Open
cwperks wants to merge 8 commits intoopensearch-project:mainfrom
cwperks:custom-prefix
Open

Allow action prefixes to be registered from plugins#20913
cwperks wants to merge 8 commits intoopensearch-project:mainfrom
cwperks:custom-prefix

Conversation

@cwperks
Copy link
Member

@cwperks cwperks commented Mar 18, 2026

Description

Companion PR in Security plugin to showcase how this can be used: opensearch-project/security#6020

The changes in this PR allow action prefixes to be registered from plugins. This gives more flexibility in action naming to help make more readable action-names (especially in the context of resource sharing).

Action names with custom prefix would be used for actions pertaining to a single resource (a single doc containing metadata in a system index)

Take these examples proposed for the reporting plugin:

  • cluster:admin/opendistro/reports/instance/get -> report_instance:get
  • cluster:admin/opendistro/reports/instance/list -> this would stay the same as a cluster_permission as it does not pertain to a single resource
  • cluster:admin/opendistro/reports/menu/download -> report_instance:download

By adding custom prefixes, we get more flexibility with action naming in an aim to simplify how our current permissions system works.

Related Issues

Related to opensearch-project/security#4500

Check List

  • Functionality includes testing.
  • API changes companion pull request created, if applicable.
  • Public documentation issue/PR created, if applicable.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

cwperks added 4 commits March 18, 2026 11:27
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
Signed-off-by: Craig Perkins <cwperx@amazon.com>
@cwperks cwperks requested review from a team and peternied as code owners March 18, 2026 20:15
Signed-off-by: Craig Perkins <cwperx@amazon.com>
@github-actions
Copy link
Contributor

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit d258baa.

PathLineSeverityDescription
server/src/main/java/org/opensearch/rest/NamedRoute.java87mediumThe `validateLegacyActionNames()` method is removed, eliminating prefix validation for legacy action names in the Builder. The replacement validation added in ActionModule.initRestHandlers() only iterates over `namedRoute.actionNames()`, not `namedRoute.legacyActionNames()`, leaving a gap where legacy action names with arbitrary (non-standard) prefixes can be registered without any enforcement. This could allow bypassing the prefix allowlist for legacy-named transport actions.
server/src/main/java/org/opensearch/transport/TransportService.java1232low`registerAdditionalActionPrefixes()` is a new public method with no access control, allowing any caller (including plugins) to permanently expand the set of accepted action name prefixes. If a malicious plugin is loaded, it can whitelist arbitrary prefixes, enabling otherwise-rejected transport action names to pass `validateActionName()` silently.
server/src/test/java/org/opensearch/rest/NamedRouteTests.java97lowThe test `testNamedRouteWithInvalidLegacyActionNames` is explicitly deleted. This test verified that legacy action names with invalid prefixes were rejected. Its removal reduces regression coverage for the now-absent validation, making it easier for the gap in legacy action name validation to go undetected.

The table above displays the top 10 most important findings.

Total: 3 | Critical: 0 | High: 0 | Medium: 1 | Low: 2


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

@github-actions
Copy link
Contributor

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit 28aa469.

PathLineSeverityDescription
server/src/main/java/org/opensearch/rest/NamedRoute.java87mediumThe `validateLegacyActionNames` method is removed from `NamedRoute.Builder`, eliminating prefix validation for legacy action names. The replacement validation added in `ActionModule.initRestHandlers` only checks `namedRoute.actionNames()`, not `namedRoute.legacyActionNames()`. This means plugins can now register arbitrary strings as legacy action names without the `VALID_ACTION_PREFIXES` constraint, and the corresponding test (`testNamedRouteWithInvalidLegacyActionNames`) was also deleted to hide the regression. While plausibly intentional for legacy compatibility, it removes a security control.
server/src/main/java/org/opensearch/transport/TransportService.java1233lowThe new `registerAdditionalActionPrefixes` method allows any caller to permanently extend the set of valid action name prefixes at runtime. Because the internal `additionalActionPrefixes` set is never cleared, a plugin could widen the allowed prefix space for the lifetime of the node. The risk is low given that plugins already carry significant trust, but the mechanism could be abused by a compromised or malicious plugin to legitimize otherwise-blocked action names.

The table above displays the top 10 most important findings.

Total: 2 | Critical: 0 | High: 0 | Medium: 1 | Low: 1


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

@github-actions
Copy link
Contributor

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit 28aa469.

PathLineSeverityDescription
server/src/main/java/org/opensearch/rest/NamedRoute.java87mediumThe `validateLegacyActionNames` method and its associated validation logic are completely removed. Previously, this enforced that legacy action names started with a valid prefix from TransportService.VALID_ACTION_PREFIXES, throwing OpenSearchException on violation. The replacement validation in ActionModule.initRestHandlers only covers `namedRoute.actionNames()`, not `legacyActionNames`, leaving legacy action names with no prefix validation. The corresponding test (`testNamedRouteWithInvalidLegacyActionNames`) was also deleted, eliminating regression coverage. Plugins can now register legacy action names with arbitrary prefixes.
server/src/main/java/org/opensearch/transport/TransportService.java1232lowThe new `registerAdditionalActionPrefixes(Collection prefixes)` method allows any caller to dynamically expand the set of valid action name prefixes at runtime with no access control, sanitization, or size limit on the `additionalActionPrefixes` set. While this is the stated feature intent, it weakens the static guarantee that only known OpenSearch-controlled prefixes are valid, and an attacker with plugin-loading capability could register overly broad prefixes (e.g., a single-character prefix) to bypass action name validation entirely.

The table above displays the top 10 most important findings.

Total: 2 | Critical: 0 | High: 0 | Medium: 1 | Low: 1


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

@github-actions
Copy link
Contributor

PR Code Analyzer ❗

AI-powered 'Code-Diff-Analyzer' found issues on commit a91ccd2.

PathLineSeverityDescription
server/src/main/java/org/opensearch/rest/NamedRoute.java87mediumThe `validateLegacyActionNames` method and its enforcement are completely removed from NamedRoute. Previously, any legacy action name that did not start with a recognized prefix raised an exception. Now `legacyActionNames` are added without any validation, meaning plugins can register arbitrary strings as legacy action names. If the authorization or auditing subsystem uses these names for access-control decisions, this path could be abused to register names that bypass prefix-based policy checks. Validation is now only applied to `NamedRoute.actionNames()` inside `ActionModule.initRestHandlers`, leaving the legacy-name path unguarded.
server/src/test/java/org/opensearch/rest/NamedRouteTests.java97lowThe test `testNamedRouteWithInvalidLegacyActionNames` that asserted invalid legacy action names are rejected has been deleted. Removing a security-coverage test alongside removing the validation it covers warrants scrutiny, though it is consistent with the stated refactoring intent.
server/src/main/java/org/opensearch/action/ActionModule.java631lowThe `getPluginActionPrefixes` filter uses `TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix))` (checks whether a known prefix starts with the plugin prefix) rather than the more intuitive `prefix.startsWith(v)` (checks whether the plugin prefix begins with a known prefix). This reversed logic could allow novel plugin-defined prefixes that are substrings of existing prefixes to slip through, though exploitation would require a plugin that deliberately crafts such a prefix. Appears to be a logic error rather than intentional malice.

The table above displays the top 10 most important findings.

Total: 3 | Critical: 0 | High: 0 | Medium: 1 | Low: 2


Pull Requests Author(s): Please update your Pull Request according to the report above.

Repository Maintainer(s): You can bypass diff analyzer by adding label skip-diff-analyzer after reviewing the changes carefully, then re-run failed actions. To re-enable the analyzer, remove the label, then re-run all actions.


⚠️ Note: The Code-Diff-Analyzer helps protect against potentially harmful code patterns. Please ensure you have thoroughly reviewed the changes beforehand.

Thanks.

@cwperks cwperks added the skip-diff-analyzer Maintainer to skip code-diff-analyzer check, after reviewing issues in AI analysis. label Mar 23, 2026
@github-actions
Copy link
Contributor

github-actions bot commented Mar 23, 2026

PR Reviewer Guide 🔍

(Review updated until commit e4cccc0)

Here are some key observations to aid the review process:

🧪 PR contains tests
🔒 No security concerns identified
📝 TODO sections

🔀 No multiple PR themes
⚡ Recommended focus areas for review

Incorrect Filter Logic

In getPluginActionPrefixes(), the filter TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix)) is inverted. It checks whether any known prefix starts with the plugin prefix, but the intent is to exclude plugin prefixes that are already covered by known prefixes (i.e., the plugin prefix starts with a known prefix, or equals one). For example, a plugin action indices:data/read/custom has prefix indices, and VALID_ACTION_PREFIXES contains indices:. The current check asks if any known prefix starts with "indices""indices:" does start with "indices", so it is correctly excluded in this case. However, the logic is fragile: it should be prefix.startsWith(v) or an exact/contains match, not v.startsWith(prefix). A plugin prefix like cluster would incorrectly pass through because no known prefix starts with "cluster" exactly (they start with "cluster:" which does start with "cluster", so it happens to work), but the semantics are wrong and could produce incorrect results for edge-case prefixes.

public Set<String> getPluginActionPrefixes() {
    return actionPlugins.stream()
        .flatMap(p -> p.getActions().stream())
        .map(h -> h.getAction().name())
        .filter(name -> name.contains(":"))
        .map(name -> name.substring(0, name.indexOf(':')))
        .filter(prefix -> TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix)))
        .collect(Collectors.toSet());
}
Validation Timing Issue

The validation of action names in initRestHandlers (checking TransportService.isValidActionName(actionName)) uses only the static VALID_ACTION_PREFIXES and does not include plugin-contributed prefixes. This means REST handlers registered by plugins with custom prefixes (e.g., report_instance:get) will throw an OpenSearchException during handler registration, even though those prefixes are intended to be valid. The plugin prefixes are registered separately via registerAdditionalActionPrefixes on TransportService, but that set is not consulted here.

for (Route route : handler.routes()) {
    if (route instanceof NamedRoute namedRoute) {
        for (String actionName : namedRoute.actionNames()) {
            if (!TransportService.isValidActionName(actionName)) {
                throw new OpenSearchException(
                    "Invalid action name ["
                        + actionName
                        + "]. It must start with one of: "
                        + TransportService.VALID_ACTION_PREFIXES
                );
            }
        }
    }
}
Thread Safety

additionalActionPrefixes is a HashSet that can be written via registerAdditionalActionPrefixes and read concurrently via validateActionName or isValidActionName. There is no synchronization, which can cause data races in a multi-threaded environment. Consider using ConcurrentHashMap.newKeySet() or Collections.synchronizedSet.

private final Set<String> additionalActionPrefixes;

/**
 * Registers additional valid action name prefixes contributed by plugins.
 */
public void registerAdditionalActionPrefixes(Collection<String> prefixes) {
    additionalActionPrefixes.addAll(prefixes);
}

for (Route route : handler.routes()) {
if (route instanceof NamedRoute namedRoute) {
for (String actionName : namedRoute.actionNames()) {
if (!TransportService.isValidActionName(actionName)) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic retains the validation currently in NamedRoute but enforces on node bootstrap.

This line is equivalent to this.legacyActionNames.addAll(validateLegacyActionNames(legacyActionNames));

@github-actions
Copy link
Contributor

github-actions bot commented Mar 23, 2026

PR Code Suggestions ✨

Latest suggestions up to e4cccc0
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Use plugin prefixes in action name validation

The validation in initRestHandlers uses the static isValidActionName(String)
overload, which only checks VALID_ACTION_PREFIXES and ignores the plugin-contributed
prefixes collected by getPluginActionPrefixes(). This means plugin-registered action
names with novel prefixes will always fail validation here, defeating the purpose of
the PR. The two-argument overload isValidActionName(actionName, additionalPrefixes)
should be used with the plugin prefixes.

server/src/main/java/org/opensearch/action/ActionModule.java [876-889]

+Set<String> pluginPrefixes = getPluginActionPrefixes();
 for (Route route : handler.routes()) {
     if (route instanceof NamedRoute namedRoute) {
         for (String actionName : namedRoute.actionNames()) {
-            if (!TransportService.isValidActionName(actionName)) {
+            if (!TransportService.isValidActionName(actionName, pluginPrefixes)) {
                 throw new OpenSearchException(
                     "Invalid action name ["
                         + actionName
                         + "]. It must start with one of: "
                         + TransportService.VALID_ACTION_PREFIXES
                 );
             }
         }
     }
 }
Suggestion importance[1-10]: 9

__

Why: This is a critical correctness issue: the validation in initRestHandlers uses isValidActionName(actionName) which only checks VALID_ACTION_PREFIXES, so plugin-registered action names with novel prefixes will always fail validation, completely defeating the purpose of the PR. The fix to use isValidActionName(actionName, pluginPrefixes) is necessary for the feature to work correctly.

High
Fix inverted prefix containment check

The filter logic is inverted: it checks if any known valid prefix starts with the
plugin prefix, but it should check if the plugin prefix starts with any known valid
prefix. For example, a plugin prefix "indices" would not be filtered out because no
known prefix starts with "indices", even though "indices:" is a known valid prefix.
The correct check should be noneMatch(v -> prefix.startsWith(v) ||
v.startsWith(prefix)) or simply check if the full action name would already be
valid.

server/src/main/java/org/opensearch/action/ActionModule.java [637]

-.filter(prefix -> TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix)))
+.filter(prefix -> TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix) || prefix.startsWith(v)))
Suggestion importance[1-10]: 7

__

Why: The filter logic is indeed potentially incorrect. For example, a plugin prefix "indices" would pass the filter because no known prefix starts with "indices" (the known prefix is "indices:"), even though actions with that prefix would already be valid. The fix to check both directions (v.startsWith(prefix) || prefix.startsWith(v)) is more robust and correct.

Medium
General
Align parameter type for consistency

The method signature accepts a Set but the additionalActionPrefixes field is
declared as Set while registerAdditionalActionPrefixes accepts a Collection. For
consistency and to allow callers to pass any collection type, consider changing the
parameter type to Collection. This also aligns with the
registerAdditionalActionPrefixes method signature.

server/src/main/java/org/opensearch/transport/TransportService.java [1252]

-public static boolean isValidActionName(String actionName, Set<String> additionalPrefixes) {
+public static boolean isValidActionName(String actionName, Collection<String> additionalPrefixes) {
Suggestion importance[1-10]: 3

__

Why: This is a minor style/consistency improvement to align the isValidActionName parameter type with registerAdditionalActionPrefixes. It has low functional impact but improves API consistency.

Low

Previous suggestions

Suggestions up to commit a91ccd2
CategorySuggestion                                                                                                                                    Impact
Possible issue
Include plugin prefixes in route validation

The validation in initRestHandlers calls the static isValidActionName(actionName)
which only checks VALID_ACTION_PREFIXES and does not consider the plugin-contributed
additional prefixes. This means plugin-registered handlers with novel (but valid)
action prefixes will always fail validation here. The overloaded
isValidActionName(actionName, additionalPrefixes) should be used instead, passing
the plugin prefixes collected from getPluginActionPrefixes().

server/src/main/java/org/opensearch/action/ActionModule.java [876-889]

+Set<String> pluginPrefixes = getPluginActionPrefixes();
 for (Route route : handler.routes()) {
     if (route instanceof NamedRoute namedRoute) {
         for (String actionName : namedRoute.actionNames()) {
-            if (!TransportService.isValidActionName(actionName)) {
+            if (!TransportService.isValidActionName(actionName, pluginPrefixes)) {
                 throw new OpenSearchException(
                     "Invalid action name ["
                         + actionName
                         + "]. It must start with one of: "
                         + TransportService.VALID_ACTION_PREFIXES
                 );
             }
         }
     }
 }
Suggestion importance[1-10]: 8

__

Why: The validation in initRestHandlers uses the static isValidActionName(actionName) which only checks VALID_ACTION_PREFIXES, so plugin-registered handlers with novel but valid action prefixes will incorrectly fail validation. Using isValidActionName(actionName, pluginPrefixes) with the plugin-contributed prefixes is necessary for correctness.

Medium
Fix inverted prefix containment check

The filter logic is inverted: it checks if any known valid prefix starts with the
plugin prefix, but it should check if the plugin prefix starts with any known valid
prefix. For example, a plugin prefix "indices" would not be filtered out because no
known prefix starts with "indices", even though "indices:" is a known valid prefix.
The condition should use prefix.startsWith(v) or check if the action name itself
would pass isValidActionName.

server/src/main/java/org/opensearch/action/ActionModule.java [637]

-.filter(prefix -> TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix)))
+.filter(prefix -> TransportService.VALID_ACTION_PREFIXES.stream().noneMatch(v -> v.startsWith(prefix + ":")))
Suggestion importance[1-10]: 7

__

Why: The filter logic uses v.startsWith(prefix) which checks if a known valid prefix starts with the plugin prefix, but the intent is to exclude plugin prefixes that are already covered by known prefixes. The correct check should be whether the plugin prefix starts with a known valid prefix (e.g., v.startsWith(prefix + ":") or similar). This is a real logic bug that could cause known prefixes like "indices" to not be filtered out correctly.

Medium
General
Guard against null additional prefixes set

The method accepts a Set but the instance field additionalActionPrefixes is a Set
while registerAdditionalActionPrefixes accepts a Collection. For consistency and to
avoid a NullPointerException if null is passed as additionalPrefixes, a null check
should be added.

server/src/main/java/org/opensearch/transport/TransportService.java [1252-1264]

 public static boolean isValidActionName(String actionName, Set<String> additionalPrefixes) {
     for (String prefix : VALID_ACTION_PREFIXES) {
         if (actionName.startsWith(prefix)) {
             return true;
         }
     }
-    for (String prefix : additionalPrefixes) {
-        if (actionName.startsWith(prefix)) {
-            return true;
+    if (additionalPrefixes != null) {
+        for (String prefix : additionalPrefixes) {
+            if (actionName.startsWith(prefix)) {
+                return true;
+            }
         }
     }
     return false;
 }
Suggestion importance[1-10]: 3

__

Why: Adding a null check for additionalPrefixes is a minor defensive improvement, but the method is always called with Set.of() (non-null) in the new overload, making a NullPointerException unlikely in practice. The improvement is marginal.

Low

@github-actions
Copy link
Contributor

❌ Gradle check result for a91ccd2: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Contributor

❌ Gradle check result for a91ccd2: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@cwperks
Copy link
Member Author

cwperks commented Mar 23, 2026

Latest failure

> Task :plugins:ingestion-kinesis:internalClusterTest

REPRODUCE WITH: ./gradlew ':plugins:ingestion-kinesis:internalClusterTest' --tests 'org.opensearch.plugin.kinesis.IngestFromKinesisIT.testAllActiveIngestion' -Dtests.seed=97A82CDA086A7A59 -Dtests.security.manager=false -Dtests.jvm.argline="-XX:TieredStopAtLevel=1 -XX:ReservedCodeCacheSize=64m" -Dtests.locale=syr-IQ -Dtests.timezone=Europe/Ulyanovsk -Druntime.java=25

IngestFromKinesisIT > testAllActiveIngestion FAILED
    org.testcontainers.containers.ContainerLaunchException: Container startup failed for image localstack/localstack:latest
        at __randomizedtesting.SeedInfo.seed([97A82CDA086A7A59:755E52400D98699C]:0)
        at app//org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:359)
        at app//org.testcontainers.containers.GenericContainer.start(GenericContainer.java:330)
        at app//org.opensearch.plugin.kinesis.KinesisIngestionBaseIT.setupKinesis(KinesisIngestionBaseIT.java:76)
        at app//org.opensearch.plugin.kinesis.KinesisIngestionBaseIT.setup(KinesisIngestionBaseIT.java:61)
        at java.****@25.0.2/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
        at java.****@25.0.2/java.lang.reflect.Method.invoke(Method.java:565)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner.invoke(RandomizedRunner.java:1750)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner$9.evaluate(RandomizedRunner.java:972)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner$10.evaluate(RandomizedRunner.java:988)
        at app//org.opensearch.test.OpenSearchTestClusterRule$1.evaluate(OpenSearchTestClusterRule.java:369)
        at app//com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
        at app//org.junit.rules.RunRules.evaluate(RunRules.java:20)
        at app//org.apache.lucene.tests.util.TestRuleSetupTeardownChained$1.evaluate(TestRuleSetupTeardownChained.java:48)
        at app//org.apache.lucene.tests.util.AbstractBeforeAfterRule$1.evaluate(AbstractBeforeAfterRule.java:43)
        at app//org.apache.lucene.tests.util.TestRuleThreadAndTestName$1.evaluate(TestRuleThreadAndTestName.java:45)
        at app//org.apache.lucene.tests.util.TestRuleIgnoreAfterMaxFailures$1.evaluate(TestRuleIgnoreAfterMaxFailures.java:60)
        at app//org.apache.lucene.tests.util.TestRuleMarkFailure$1.evaluate(TestRuleMarkFailure.java:44)
        at app//org.junit.rules.RunRules.evaluate(RunRules.java:20)
        at app//com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
        at app//com.carrotsearch.randomizedtesting.ThreadLeakControl$StatementRunner.run(ThreadLeakControl.java:368)
        at app//com.carrotsearch.randomizedtesting.ThreadLeakControl.forkTimeoutingTask(ThreadLeakControl.java:817)
        at app//com.carrotsearch.randomizedtesting.ThreadLeakControl$3.evaluate(ThreadLeakControl.java:468)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner.runSingleTest(RandomizedRunner.java:947)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner$5.evaluate(RandomizedRunner.java:832)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner$6.evaluate(RandomizedRunner.java:883)
        at app//com.carrotsearch.randomizedtesting.RandomizedRunner$7.evaluate(RandomizedRunner.java:894)
        at app//org.apache.lucene.tests.util.AbstractBeforeAfterRule$1.evaluate(AbstractBeforeAfterRule.java:43)
        at app//com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
        at app//org.apache.lucene.tests.util.TestRuleStoreClassName$1.evaluate(TestRuleStoreClassName.java:38)
        at app//com.carrotsearch.randomizedtesting.rules.NoShadowingOrOverridesOnMethodsRule$1.evaluate(NoShadowingOrOverridesOnMethodsRule.java:40)
        at app//com.carrotsearch.randomizedtesting.rules.NoShadowingOrOverridesOnMethodsRule$1.evaluate(NoShadowingOrOverridesOnMethodsRule.java:40)
        at app//com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
        at app//com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
        at app//org.apache.lucene.tests.util.TestRuleAssertionsRequired$1.evaluate(TestRuleAssertionsRequired.java:53)
        at app//org.apache.lucene.tests.util.AbstractBeforeAfterRule$1.evaluate(AbstractBeforeAfterRule.java:43)
        at app//org.apache.lucene.tests.util.TestRuleMarkFailure$1.evaluate(TestRuleMarkFailure.java:44)
        at app//org.apache.lucene.tests.util.TestRuleIgnoreAfterMaxFailures$1.evaluate(TestRuleIgnoreAfterMaxFailures.java:60)
        at app//org.apache.lucene.tests.util.TestRuleIgnoreTestSuites$1.evaluate(TestRuleIgnoreTestSuites.java:47)
        at app//org.junit.rules.RunRules.evaluate(RunRules.java:20)
        at app//com.carrotsearch.randomizedtesting.rules.StatementAdapter.evaluate(StatementAdapter.java:36)
        at app//com.carrotsearch.randomizedtesting.ThreadLeakControl$StatementRunner.run(ThreadLeakControl.java:368)
        at java.****@25.0.2/java.lang.Thread.run(Thread.java:1474)

        Caused by:
        org.rnorth.ducttape.RetryCountExceededException: Retry limit hit with exception
            at app//org.rnorth.ducttape.unreliables.Unreliables.retryUntilSuccess(Unreliables.java:88)
            at app//org.testcontainers.containers.GenericContainer.doStart(GenericContainer.java:344)
            ... 41 more

@github-actions
Copy link
Contributor

❌ Gradle check result for a91ccd2: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Contributor

❌ Gradle check result for a91ccd2: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Contributor

Persistent review updated to latest commit e4cccc0

@github-actions
Copy link
Contributor

✅ Gradle check result for e4cccc0: SUCCESS

@codecov
Copy link

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 53.57143% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.29%. Comparing base (fb5d661) to head (e4cccc0).
⚠️ Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
...ava/org/opensearch/transport/TransportService.java 25.00% 8 Missing and 1 partial ⚠️
.../main/java/org/opensearch/action/ActionModule.java 71.42% 3 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #20913      +/-   ##
============================================
+ Coverage     73.24%   73.29%   +0.05%     
- Complexity    72510    72555      +45     
============================================
  Files          5819     5819              
  Lines        331373   331391      +18     
  Branches      47882    47887       +5     
============================================
+ Hits         242707   242887     +180     
+ Misses        69201    68979     -222     
- Partials      19465    19525      +60     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

skip-diff-analyzer Maintainer to skip code-diff-analyzer check, after reviewing issues in AI analysis.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant