Skip to content

[GRPC] Handle ShardSearchFailure properly - #20641

Merged
karenyrx merged 3 commits into
opensearch-project:mainfrom
karenyrx:grpcshard
Feb 21, 2026
Merged

[GRPC] Handle ShardSearchFailure properly#20641
karenyrx merged 3 commits into
opensearch-project:mainfrom
karenyrx:grpcshard

Conversation

@karenyrx

@karenyrx karenyrx commented Feb 17, 2026

Copy link
Copy Markdown
Contributor

Description

Fix the ShardSearchFailure proto utils after API spec fix in opensearch-project/opensearch-api-specification#1040

Changes to the Search shard failure response - it will include a new failures2 section, like:

 {
    "xShards": {
      "failed": 1,
      "failures": [        // <-- OLD field (legacy, for backward compatibility)
        {
          "index": "shard-fail-test",
          "node": "VI9ac3rmTB6uUwyheEivBg",
          "reason": {...}
          // Note: "primary" field exists in the old proto type, but can never be set (becuase search responses do not differentiate between primary vs. replica)
  (defaults to false)
        }
      ],
      "failures2": [       // <-- NEW field (ShardSearchFailure protobuf type)
        {
          "index": "shard-fail-test",
          "node": "VI9ac3rmTB6uUwyheEivBg",
          "reason": {...}
          // Note: NO "primary" field in this proto type
        }
      ]
    }
  }

Test Plan

Search request:

~/OpenSearch on [grpcshard] % 
grpcurl -plaintext \
  -import-path ~/OpenSearch \
  -proto protos/services/search_service.proto \
  -d @ localhost:9400 \
  org.opensearch.protobufs.services.SearchService/Search <<'EOM'
{
  "index": ["shard-fail-test"],
  "search_request_body": {
    "query": {
      "bool": {
        "filter": {
          "script": {
            "script": {
              "inline": {
                "source": "throw new RuntimeException('Test shard failure')"
              }
            }
          }
        }
      }
    }
  }
}
EOM

response:

{
  "took": "4",
  "xShards": {
    "failed": 1,
    "successful": 1,
    "total": 2,
    "failures": [
      {
        "index": "shard-fail-test",
        "node": "AZB7zwXaS9mm-5GcUPmmQg",
        "reason": {
          "type": "script_exception",
          "reason": "runtime error",
          "stackTrace": "ScriptException[runtime error]; nested: RuntimeException[Test shard failure];\n\tat org.opensearch.painless.PainlessScript.convertToScriptException(PainlessScript.java:117)\n\tat org.opensearch.painless.PainlessScript$Script.execute(throw new RuntimeException('Test shard failure'):1)\n\tat org.opensearch.index.query.ScriptQueryBuilder$ScriptQuery$1$1.matches(ScriptQueryBuilder.java:227)\n\tat org.apache.lucene.search.ConstantScoreScorer$1.matches(ConstantScoreScorer.java:103)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.scoreTwoPhaseIterator(Weight.java:311)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.score(Weight.java:282)\n\tat org.opensearch.search.internal.CancellableBulkScorer.score(CancellableBulkScorer.java:71)\n\tat org.opensearch.search.internal.ContextIndexSearcher.searchLeaf(ContextIndexSearcher.java:367)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:316)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:280)\n\tat org.opensearch.search.query.QueryPhase.searchWithCollector(QueryPhase.java:355)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:492)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:449)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWith(QueryPhase.java:432)\n\tat org.opensearch.search.query.QueryPhaseSearcherWrapper.searchWith(QueryPhaseSearcherWrapper.java:60)\n\tat org.opensearch.search.query.QueryPhase.executeInternal(QueryPhase.java:283)\n\tat org.opensearch.search.query.QueryPhase.execute(QueryPhase.java:156)\n\tat org.opensearch.search.SearchService.loadOrExecuteQueryPhase(SearchService.java:787)\n\tat org.opensearch.search.SearchService.executeQueryPhase(SearchService.java:885)\n\tat org.opensearch.search.SearchService$2.lambda$onResponse$0(SearchService.java:843)\n\tat org.opensearch.action.ActionRunnable.lambda$supply$0(ActionRunnable.java:74)\n\tat org.opensearch.action.ActionRunnable$2.doRun(ActionRunnable.java:89)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.threadpool.TaskAwareRunnable.doRun(TaskAwareRunnable.java:78)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.common.util.concurrent.TimedRunnable.doRun(TimedRunnable.java:59)\n\tat org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:977)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)\n\tat java.base/java.lang.Thread.run(Thread.java:1583)\nCaused by: java.lang.RuntimeException: Test shard failure\n\tat org.opensearch.painless.PainlessScript$Script.execute(throw new RuntimeException('Test shard failure'):7)\n\t... 29 more\n",
          "causedBy": {
            "type": "runtime_exception",
            "reason": "Test shard failure",
            "stackTrace": "java.lang.RuntimeException: Test shard failure\n\tat org.opensearch.painless.PainlessScript$Script.execute(throw new RuntimeException('Test shard failure'):7)\n\tat org.opensearch.index.query.ScriptQueryBuilder$ScriptQuery$1$1.matches(ScriptQueryBuilder.java:227)\n\tat org.apache.lucene.search.ConstantScoreScorer$1.matches(ConstantScoreScorer.java:103)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.scoreTwoPhaseIterator(Weight.java:311)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.score(Weight.java:282)\n\tat org.opensearch.search.internal.CancellableBulkScorer.score(CancellableBulkScorer.java:71)\n\tat org.opensearch.search.internal.ContextIndexSearcher.searchLeaf(ContextIndexSearcher.java:367)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:316)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:280)\n\tat org.opensearch.search.query.QueryPhase.searchWithCollector(QueryPhase.java:355)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:492)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:449)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWith(QueryPhase.java:432)\n\tat org.opensearch.search.query.QueryPhaseSearcherWrapper.searchWith(QueryPhaseSearcherWrapper.java:60)\n\tat org.opensearch.search.query.QueryPhase.executeInternal(QueryPhase.java:283)\n\tat org.opensearch.search.query.QueryPhase.execute(QueryPhase.java:156)\n\tat org.opensearch.search.SearchService.loadOrExecuteQueryPhase(SearchService.java:787)\n\tat org.opensearch.search.SearchService.executeQueryPhase(SearchService.java:885)\n\tat org.opensearch.search.SearchService$2.lambda$onResponse$0(SearchService.java:843)\n\tat org.opensearch.action.ActionRunnable.lambda$supply$0(ActionRunnable.java:74)\n\tat org.opensearch.action.ActionRunnable$2.doRun(ActionRunnable.java:89)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.threadpool.TaskAwareRunnable.doRun(TaskAwareRunnable.java:78)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.common.util.concurrent.TimedRunnable.doRun(TimedRunnable.java:59)\n\tat org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:977)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)\n\tat java.base/java.lang.Thread.run(Thread.java:1583)\n"
          },
          "metadata": {
            "fields": {
              "lang": {
                "string": "painless"
              },
              "position": {
                "objectMap": {
                  "fields": {
                    "end": {
                      "int32": 48
                    },
                    "offset": {
                      "int32": 6
                    },
                    "start": {
                      "int32": 0
                    }
                  }
                }
              },
              "script": {
                "string": "throw new RuntimeException('Test shard failure')"
              },
              "script_stack": {
                "listValue": {
                  "value": [
                    {
                      "string": "throw new RuntimeException('Test shard failure')"
                    },
                    {
                      "string": "      ^---- HERE"
                    }
                  ]
                }
              }
            }
          }
        },
        "shard": 1
      }
    ],
    "skipped": 0,
    "failures2": [
      {
        "shard": 1,
        "index": "shard-fail-test",
        "node": "AZB7zwXaS9mm-5GcUPmmQg",
        "reason": {
          "type": "script_exception",
          "reason": "runtime error",
          "stackTrace": "ScriptException[runtime error]; nested: RuntimeException[Test shard failure];\n\tat org.opensearch.painless.PainlessScript.convertToScriptException(PainlessScript.java:117)\n\tat org.opensearch.painless.PainlessScript$Script.execute(throw new RuntimeException('Test shard failure'):1)\n\tat org.opensearch.index.query.ScriptQueryBuilder$ScriptQuery$1$1.matches(ScriptQueryBuilder.java:227)\n\tat org.apache.lucene.search.ConstantScoreScorer$1.matches(ConstantScoreScorer.java:103)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.scoreTwoPhaseIterator(Weight.java:311)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.score(Weight.java:282)\n\tat org.opensearch.search.internal.CancellableBulkScorer.score(CancellableBulkScorer.java:71)\n\tat org.opensearch.search.internal.ContextIndexSearcher.searchLeaf(ContextIndexSearcher.java:367)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:316)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:280)\n\tat org.opensearch.search.query.QueryPhase.searchWithCollector(QueryPhase.java:355)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:492)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:449)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWith(QueryPhase.java:432)\n\tat org.opensearch.search.query.QueryPhaseSearcherWrapper.searchWith(QueryPhaseSearcherWrapper.java:60)\n\tat org.opensearch.search.query.QueryPhase.executeInternal(QueryPhase.java:283)\n\tat org.opensearch.search.query.QueryPhase.execute(QueryPhase.java:156)\n\tat org.opensearch.search.SearchService.loadOrExecuteQueryPhase(SearchService.java:787)\n\tat org.opensearch.search.SearchService.executeQueryPhase(SearchService.java:885)\n\tat org.opensearch.search.SearchService$2.lambda$onResponse$0(SearchService.java:843)\n\tat org.opensearch.action.ActionRunnable.lambda$supply$0(ActionRunnable.java:74)\n\tat org.opensearch.action.ActionRunnable$2.doRun(ActionRunnable.java:89)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.threadpool.TaskAwareRunnable.doRun(TaskAwareRunnable.java:78)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.common.util.concurrent.TimedRunnable.doRun(TimedRunnable.java:59)\n\tat org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:977)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)\n\tat java.base/java.lang.Thread.run(Thread.java:1583)\nCaused by: java.lang.RuntimeException: Test shard failure\n\tat org.opensearch.painless.PainlessScript$Script.execute(throw new RuntimeException('Test shard failure'):7)\n\t... 29 more\n",
          "causedBy": {
            "type": "runtime_exception",
            "reason": "Test shard failure",
            "stackTrace": "java.lang.RuntimeException: Test shard failure\n\tat org.opensearch.painless.PainlessScript$Script.execute(throw new RuntimeException('Test shard failure'):7)\n\tat org.opensearch.index.query.ScriptQueryBuilder$ScriptQuery$1$1.matches(ScriptQueryBuilder.java:227)\n\tat org.apache.lucene.search.ConstantScoreScorer$1.matches(ConstantScoreScorer.java:103)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.scoreTwoPhaseIterator(Weight.java:311)\n\tat org.apache.lucene.search.Weight$DefaultBulkScorer.score(Weight.java:282)\n\tat org.opensearch.search.internal.CancellableBulkScorer.score(CancellableBulkScorer.java:71)\n\tat org.opensearch.search.internal.ContextIndexSearcher.searchLeaf(ContextIndexSearcher.java:367)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:316)\n\tat org.opensearch.search.internal.ContextIndexSearcher.search(ContextIndexSearcher.java:280)\n\tat org.opensearch.search.query.QueryPhase.searchWithCollector(QueryPhase.java:355)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:492)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWithCollector(QueryPhase.java:449)\n\tat org.opensearch.search.query.QueryPhase$DefaultQueryPhaseSearcher.searchWith(QueryPhase.java:432)\n\tat org.opensearch.search.query.QueryPhaseSearcherWrapper.searchWith(QueryPhaseSearcherWrapper.java:60)\n\tat org.opensearch.search.query.QueryPhase.executeInternal(QueryPhase.java:283)\n\tat org.opensearch.search.query.QueryPhase.execute(QueryPhase.java:156)\n\tat org.opensearch.search.SearchService.loadOrExecuteQueryPhase(SearchService.java:787)\n\tat org.opensearch.search.SearchService.executeQueryPhase(SearchService.java:885)\n\tat org.opensearch.search.SearchService$2.lambda$onResponse$0(SearchService.java:843)\n\tat org.opensearch.action.ActionRunnable.lambda$supply$0(ActionRunnable.java:74)\n\tat org.opensearch.action.ActionRunnable$2.doRun(ActionRunnable.java:89)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.threadpool.TaskAwareRunnable.doRun(TaskAwareRunnable.java:78)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat org.opensearch.common.util.concurrent.TimedRunnable.doRun(TimedRunnable.java:59)\n\tat org.opensearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:977)\n\tat org.opensearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:52)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144)\n\tat java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642)\n\tat java.base/java.lang.Thread.run(Thread.java:1583)\n"
          },
          "metadata": {
            "fields": {
              "lang": {
                "string": "painless"
              },
              "position": {
                "objectMap": {
                  "fields": {
                    "end": {
                      "int32": 48
                    },
                    "offset": {
                      "int32": 6
                    },
                    "start": {
                      "int32": 0
                    }
                  }
                }
              },
              "script": {
                "string": "throw new RuntimeException('Test shard failure')"
              },
              "script_stack": {
                "listValue": {
                  "value": [
                    {
                      "string": "throw new RuntimeException('Test shard failure')"
                    },
                    {
                      "string": "      ^---- HERE"
                    }
                  ]
                }
              }
            }
          }
        }
      }
    ]
  },
  "hits": {
    "total": {
      "totalHits": {
        "relation": "TOTAL_HITS_RELATION_EQ"
      }
    },
    "maxScore": {
      "nullValue": "NULL_VALUE_NULL"
    }
  }
}

Related Issues

Resolves #[Issue number to be closed when this PR is merged]

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.

@coderabbitai

coderabbitai Bot commented Feb 17, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

This PR upgrades the opensearch-protobufs dependency from 1.2.0 to 1.3.0 and refactors ShardSearchFailure serialization to use newly available protobuf types while maintaining backward compatibility through a deprecated legacy conversion method.

Changes

Cohort / File(s) Summary
Dependency and Documentation Updates
CHANGELOG.md, gradle/libs.versions.toml
Version bump documentation and catalog update for opensearchprotobufs 1.2.0 → 1.3.0.
License Checksum Files
modules/transport-grpc/licenses/protobufs-*.jar.sha1, modules/transport-grpc/spi/licenses/protobufs-*.jar.sha1
SHA-1 checksum updates corresponding to protobuf library version upgrade.
Proto Utilities Refactoring
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/.../ShardSearchFailureProtoUtils.java, modules/transport-grpc/src/main/java/.../ShardOperationFailedExceptionProtoUtils.java
ShardSearchFailureProtoUtils updated to return new org.opensearch.protobufs.ShardSearchFailure from toProto; added deprecated toLegacyProto method for backward compatibility. ShardOperationFailedExceptionProtoUtils modified to route ShardSearchFailure through toLegacyProto.
Search Statistics Integration
modules/transport-grpc/src/main/java/.../ShardStatisticsProtoUtils.java
Added handling for new failures2 field in addition to legacy failures field when ShardSearchFailure instances are encountered.
Test Coverage
modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/.../ShardSearchFailureProtoUtilsTests.java, modules/transport-grpc/src/test/java/.../ShardStatisticsProtoUtilsTests.java, modules/transport-grpc/src/test/java/.../ShardOperationFailedExceptionProtoUtilsTests.java
Comprehensive new test suite validating toProto/toLegacyProto conversions, dual-field population for migration scenarios, and backward compatibility across legacy and new failure representations.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested labels

distributed framework, dependencies

🚥 Pre-merge checks | ✅ 1 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description provides context for the change (fixing ShardSearchFailure after API spec fix) but is minimal and omits the Description section content required by the template. Expand the Description section to explain what the change achieves (e.g., how ShardSearchFailure is now properly handled and why the API spec change required code changes).
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title '[GRPC] Handle ShardSearchFailure properly' directly summarizes the main change: fixing ShardSearchFailure proto utilities in the GRPC transport module.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

❗ AI-powered Code-Diff-Analyzer found issues on commit 7e7fb12.

PathLineSeverityDescription
Screenshot 2026-02-16 at 6.12.49 PM.png0mediumBinary image file added without corresponding documentation changes. Binary files can be used for steganography or covert data channels. While screenshots are commonly added to repositories, this file is not referenced in any documentation or code changes in this diff, making its purpose unclear.
gradle/libs.versions.toml27lowDependency version bump for opensearchprotobufs from 1.2.0 to 1.3.0. Represents potential supply chain risk if the new version was compromised. However, the code changes throughout the diff are consistent with legitimate use of new proto types introduced in 1.3.0, suggesting this is a standard dependency upgrade.

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
Copy Markdown
Contributor

❌ Gradle check result for 75ef5bc: 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?

Signed-off-by: Karen X <karenxyr@gmail.com>
@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for a631bb2: 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?

Signed-off-by: Karen X <karenxyr@gmail.com>
@karenyrx
karenyrx marked this pull request as ready for review February 17, 2026 19:04
@karenyrx
karenyrx requested a review from a team as a code owner February 17, 2026 19:04
@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 79c8f06: 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?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java (1)

41-51: ⚠️ Potential issue | 🟡 Minor

Add missing space in the unsupported-exception message.

The default message concatenates the class name and “cannot” without spacing, making logs harder to read.

🩹 Proposed fix
             default -> throw new UnsupportedOperationException(
-                "Unsupported ShardOperationFailedException " + exception.getClass().getName() + "cannot be converted to proto."
+                "Unsupported ShardOperationFailedException " + exception.getClass().getName() + " cannot be converted to proto."
             );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java`
around lines 41 - 51, The default branch in
ShardOperationFailedExceptionProtoUtils' switch builds an error message by
concatenating exception.getClass().getName() and "cannot" without a space;
update the default UnsupportedOperationException message in the switch (the
default -> ... branch) to insert a space before "cannot" so it reads "... " +
exception.getClass().getName() + " cannot be converted to proto." ensuring
clearer logs.
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6760346 and 79c8f06.

📒 Files selected for processing (12)
  • CHANGELOG.md
  • gradle/libs.versions.toml
  • modules/transport-grpc/licenses/protobufs-1.2.0.jar.sha1
  • modules/transport-grpc/licenses/protobufs-1.3.0.jar.sha1
  • modules/transport-grpc/spi/licenses/protobufs-1.2.0.jar.sha1
  • modules/transport-grpc/spi/licenses/protobufs-1.3.0.jar.sha1
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtils.java
  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtilsTests.java
  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtilsTests.java
  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtilsTests.java
💤 Files with no reviewable changes (2)
  • modules/transport-grpc/licenses/protobufs-1.2.0.jar.sha1
  • modules/transport-grpc/spi/licenses/protobufs-1.2.0.jar.sha1
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: karenyrx
Repo: opensearch-project/OpenSearch PR: 20335
File: modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/request/search/SearchSourceBuilderProtoUtils.java:155-172
Timestamp: 2026-01-02T19:23:29.698Z
Learning: The gRPC search API in OpenSearch is marked as "experimental" in official documentation, so changes to proto schemas that remove previously unsupported fields (those throwing UnsupportedOperationException) are not considered breaking changes.
📚 Learning: 2026-01-02T19:23:16.689Z
Learnt from: karenyrx
Repo: opensearch-project/OpenSearch PR: 20335
File: modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/request/search/SearchSourceBuilderProtoUtils.java:155-172
Timestamp: 2026-01-02T19:23:16.689Z
Learning: In OpenSearch's gRPC transport module, treat removals of previously-unsupported fields (those throwing UnsupportedOperationException) from experimental proto schemas as non-breaking changes. When reviewing changes to proto-related Java code in this module, document that such removals do not count as breaking API changes, and ensure tests reflect compatibility expectations accordingly.

Applied to files:

  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtilsTests.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtils.java
  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtilsTests.java
  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtilsTests.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java
📚 Learning: 2026-01-02T19:23:29.698Z
Learnt from: karenyrx
Repo: opensearch-project/OpenSearch PR: 20335
File: modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/request/search/SearchSourceBuilderProtoUtils.java:155-172
Timestamp: 2026-01-02T19:23:29.698Z
Learning: In the transport-grpc module, suggest and aggregations protos were removed from SearchRequestBody in protobufs 1.0.0 because they haven't been vetted for accuracy in the API specification. The URL parameter suggest support (suggest_field, suggest_mode, suggest_size, suggest_text) is a minimized subset and not intended as a replacement for full Suggester functionality.

Applied to files:

  • modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtilsTests.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtils.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java
  • modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java
📚 Learning: 2026-01-02T19:23:29.698Z
Learnt from: karenyrx
Repo: opensearch-project/OpenSearch PR: 20335
File: modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/request/search/SearchSourceBuilderProtoUtils.java:155-172
Timestamp: 2026-01-02T19:23:29.698Z
Learning: The gRPC search API in OpenSearch is marked as "experimental" in official documentation, so changes to proto schemas that remove previously unsupported fields (those throwing UnsupportedOperationException) are not considered breaking changes.

Applied to files:

  • gradle/libs.versions.toml
  • CHANGELOG.md
🧬 Code graph analysis (5)
modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtilsTests.java (1)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java (1)
  • ShardOperationFailedExceptionProtoUtils (24-54)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtils.java (2)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java (1)
  • ShardOperationFailedExceptionProtoUtils (24-54)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java (1)
  • ShardSearchFailureProtoUtils (21-69)
modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtilsTests.java (1)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java (1)
  • ShardSearchFailureProtoUtils (21-69)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java (1)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/opensearchexception/OpenSearchExceptionProtoUtils.java (1)
  • OpenSearchExceptionProtoUtils (47-251)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java (1)
modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java (1)
  • ShardSearchFailureProtoUtils (21-69)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: gradle-check
🔇 Additional comments (23)
CHANGELOG.md (1)

32-32: LGTM — changelog entry added correctly.

gradle/libs.versions.toml (1)

27-27: Remove unused version entry or add missing library alias.

Line 27 defines opensearchprotobufs = "1.3.0" but no library in the [libraries] section references this version. Either remove the unused version entry or add the missing library alias that uses it (e.g., opensearchprotobufs = { group = "...", name = "...", version.ref = "opensearchprotobufs" }).

modules/transport-grpc/licenses/protobufs-1.3.0.jar.sha1 (1)

1-1: Both checksum files are already in sync; published jar verification requires external network access.

The two checksum files (modules/transport-grpc/licenses/protobufs-1.3.0.jar.sha1 and modules/transport-grpc/spi/licenses/protobufs-1.3.0.jar.sha1) both contain the identical checksum a141d00a9de80085436c648502d1b015fd89b9f6, confirming they are kept synchronized. However, verification that this checksum matches the published org.opensearch:protobufs 1.3.0 jar requires downloading from Maven Central, which requires external network access outside the sandbox environment.

modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtils.java (2)

34-45: Good: new ShardSearchFailure proto mapping is complete.

Field population mirrors the XContent shape and captures shard/index/node/reason as expected.


47-67: Legacy conversion keeps back-compat and omits primary as intended.

The deprecated path preserves older clients while aligning with search-failure semantics.

modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtils.java (1)

61-68: Nice dual-population of failures and failures_2 for ShardSearchFailure.

This keeps legacy clients working while enabling the new proto type.

modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardSearchFailureProtoUtilsTests.java (5)

21-41: Covers nodeId propagation and reason presence for new proto.


43-55: Good guard for missing nodeId in new proto conversion.


57-78: Legacy path validated, including default primary=false.


80-92: Legacy conversion without nodeId is well covered.


94-112: Nice parity check between legacy and new proto data.

modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtilsTests.java (1)

37-48: Good coverage for legacy primary default behavior.

modules/transport-grpc/src/test/java/org/opensearch/transport/grpc/proto/response/search/ShardStatisticsProtoUtilsTests.java (11)

22-29: Covers basic shard-stat fields.


31-39: Negative skipped handling is well tested.


41-49: No-failure scenario validates empty lists.


51-59: Null failures input handled and tested.


61-90: ShardSearchFailure populates both legacy and new fields.


92-125: Back-compat mapping between legacy and new failure protos is verified.


127-145: Mixed-type expectations for failures_2 are covered.


147-186: Multi-failure dual-field consistency is validated.


188-212: Old-client legacy read path is thoroughly tested.


214-239: New-client failures_2 read path coverage looks solid.


241-270: Gradual migration scenario is well exercised.

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In
`@modules/transport-grpc/src/main/java/org/opensearch/transport/grpc/proto/response/exceptions/shardoperationfailedexception/ShardOperationFailedExceptionProtoUtils.java`:
- Around line 41-51: The default branch in
ShardOperationFailedExceptionProtoUtils' switch builds an error message by
concatenating exception.getClass().getName() and "cannot" without a space;
update the default UnsupportedOperationException message in the switch (the
default -> ... branch) to insert a space before "cannot" so it reads "... " +
exception.getClass().getName() + " cannot be converted to proto." ensuring
clearer logs.

---

Duplicate comments:
In `@modules/transport-grpc/spi/licenses/protobufs-1.3.0.jar.sha1`:
- Line 1: The review comment on the checksum file
modules/transport-grpc/spi/licenses/protobufs-1.3.0.jar.sha1 (contents:
a141d00a9de80085436c648502d1b015fd89b9f6) is a duplicate; resolve by removing
the redundant reviewer note or marking the comment as resolved in the PR so no
code change to the checksum file is made; ensure only one authoritative comment
remains referencing that checksum string.

@github-actions

Copy link
Copy Markdown
Contributor

❌ Gradle check result for 79c8f06: 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?

Signed-off-by: Karen X <karenxyr@gmail.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ Gradle check result for d3394fd: SUCCESS

@codecov

codecov Bot commented Feb 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.61538% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 73.26%. Comparing base (6b557db) to head (d3394fd).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...nfailedexception/ShardSearchFailureProtoUtils.java 90.00% 0 Missing and 1 partial ⚠️
...oto/response/search/ShardStatisticsProtoUtils.java 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #20641      +/-   ##
============================================
- Coverage     73.32%   73.26%   -0.07%     
- Complexity    72064    72072       +8     
============================================
  Files          5781     5781              
  Lines        329395   329414      +19     
  Branches      47525    47531       +6     
============================================
- Hits         241536   241340     -196     
- Misses        68507    68791     +284     
+ Partials      19352    19283      -69     

☔ 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.

@karenyrx
karenyrx merged commit c856e62 into opensearch-project:main Feb 21, 2026
36 checks passed
jainankitk pushed a commit to jainankitk/OpenSearch that referenced this pull request Feb 23, 2026
* [GRPC] Handle ShardSearchFailure properly

Signed-off-by: Karen X <karenxyr@gmail.com>

* null check

Signed-off-by: Karen X <karenxyr@gmail.com>

---------

Signed-off-by: Karen X <karenxyr@gmail.com>
Signed-off-by: Ankit Jain <jainankitk@apache.org>
aparajita31pandey pushed a commit to aparajita31pandey/OpenSearch that referenced this pull request Apr 18, 2026
* [GRPC] Handle ShardSearchFailure properly

Signed-off-by: Karen X <karenxyr@gmail.com>

* null check

Signed-off-by: Karen X <karenxyr@gmail.com>

---------

Signed-off-by: Karen X <karenxyr@gmail.com>
Signed-off-by: Aparajita Pandey <aparajita31pandey@gmail.com>
pradeep-L pushed a commit to pradeep-L/OpenSearch that referenced this pull request Apr 21, 2026
* [GRPC] Handle ShardSearchFailure properly

Signed-off-by: Karen X <karenxyr@gmail.com>

* null check

Signed-off-by: Karen X <karenxyr@gmail.com>

---------

Signed-off-by: Karen X <karenxyr@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants