88package org .elasticsearch .xpack .rank .rrf ;
99
1010import org .apache .lucene .search .TotalHits ;
11+ import org .elasticsearch .ElasticsearchStatusException ;
12+ import org .elasticsearch .ExceptionsHelper ;
1113import org .elasticsearch .TransportVersion ;
1214import org .elasticsearch .action .ActionListener ;
1315import org .elasticsearch .action .search .SearchRequestBuilder ;
1820import org .elasticsearch .index .query .QueryBuilder ;
1921import org .elasticsearch .index .query .QueryBuilders ;
2022import org .elasticsearch .plugins .Plugin ;
23+ import org .elasticsearch .rest .RestStatus ;
2124import org .elasticsearch .search .aggregations .AggregationBuilders ;
2225import org .elasticsearch .search .aggregations .bucket .terms .Terms ;
2326import org .elasticsearch .search .builder .SearchSourceBuilder ;
4750import static org .hamcrest .CoreMatchers .is ;
4851import static org .hamcrest .Matchers .containsString ;
4952import static org .hamcrest .Matchers .equalTo ;
50- import static org .hamcrest .Matchers .greaterThan ;
5153import static org .hamcrest .Matchers .instanceOf ;
5254import static org .hamcrest .Matchers .lessThanOrEqualTo ;
5355
@@ -589,11 +591,11 @@ public void testRRFExplainWithAnotherNestedRRF() {
589591 });
590592 }
591593
592- public void testRRFInnerRetrieverSearchError () {
594+ public void testRRFInnerRetrieverAll4xxSearchErrors () {
593595 final int rankWindowSize = 100 ;
594596 final int rankConstant = 10 ;
595597 SearchSourceBuilder source = new SearchSourceBuilder ();
596- // this will throw an error during evaluation
598+ // this will throw a 4xx error during evaluation
597599 StandardRetrieverBuilder standard0 = new StandardRetrieverBuilder (
598600 QueryBuilders .constantScoreQuery (QueryBuilders .rangeQuery (VECTOR_FIELD ).gte (10 ))
599601 );
@@ -615,10 +617,57 @@ public void testRRFInnerRetrieverSearchError() {
615617 )
616618 );
617619 SearchRequestBuilder req = client ().prepareSearch (INDEX ).setSource (source );
618- Exception ex = expectThrows (IllegalStateException .class , req ::get );
619- assertThat (ex , instanceOf (IllegalStateException .class ));
620- assertThat (ex .getMessage (), containsString ("Search failed - some nested retrievers returned errors" ));
621- assertThat (ex .getSuppressed ().length , greaterThan (0 ));
620+ Exception ex = expectThrows (ElasticsearchStatusException .class , req ::get );
621+ assertThat (ex , instanceOf (ElasticsearchStatusException .class ));
622+ assertThat (
623+ ex .getMessage (),
624+ containsString (
625+ "[rrf] search failed - retrievers '[standard]' returned errors. All failures are attached as suppressed exceptions."
626+ )
627+ );
628+ assertThat (ExceptionsHelper .status (ex ), equalTo (RestStatus .BAD_REQUEST ));
629+ assertThat (ex .getSuppressed ().length , equalTo (1 ));
630+ assertThat (ex .getSuppressed ()[0 ].getCause ().getCause (), instanceOf (IllegalArgumentException .class ));
631+ }
632+
633+ public void testRRFInnerRetrieverMultipleErrorsOne5xx () {
634+ final int rankWindowSize = 100 ;
635+ final int rankConstant = 10 ;
636+ SearchSourceBuilder source = new SearchSourceBuilder ();
637+ // this will throw a 4xx error during evaluation
638+ StandardRetrieverBuilder standard0 = new StandardRetrieverBuilder (
639+ QueryBuilders .constantScoreQuery (QueryBuilders .rangeQuery (VECTOR_FIELD ).gte (10 ))
640+ );
641+ // this will throw a 5xx error
642+ TestRetrieverBuilder testRetrieverBuilder = new TestRetrieverBuilder ("val" ) {
643+ @ Override
644+ public void extractToSearchSourceBuilder (SearchSourceBuilder searchSourceBuilder , boolean compoundUsed ) {
645+ searchSourceBuilder .aggregation (AggregationBuilders .avg ("some_invalid_param" ));
646+ }
647+ };
648+ source .retriever (
649+ new RRFRetrieverBuilder (
650+ Arrays .asList (
651+ new CompoundRetrieverBuilder .RetrieverSource (standard0 , null ),
652+ new CompoundRetrieverBuilder .RetrieverSource (testRetrieverBuilder , null )
653+ ),
654+ rankWindowSize ,
655+ rankConstant
656+ )
657+ );
658+ SearchRequestBuilder req = client ().prepareSearch (INDEX ).setSource (source );
659+ Exception ex = expectThrows (ElasticsearchStatusException .class , req ::get );
660+ assertThat (ex , instanceOf (ElasticsearchStatusException .class ));
661+ assertThat (
662+ ex .getMessage (),
663+ containsString (
664+ "[rrf] search failed - retrievers '[standard, test]' returned errors. All failures are attached as suppressed exceptions."
665+ )
666+ );
667+ assertThat (ExceptionsHelper .status (ex ), equalTo (RestStatus .INTERNAL_SERVER_ERROR ));
668+ assertThat (ex .getSuppressed ().length , equalTo (2 ));
669+ assertThat (ex .getSuppressed ()[0 ].getCause ().getCause (), instanceOf (IllegalArgumentException .class ));
670+ assertThat (ex .getSuppressed ()[1 ].getCause ().getCause (), instanceOf (IllegalStateException .class ));
622671 }
623672
624673 public void testRRFInnerRetrieverErrorWhenExtractingToSource () {
0 commit comments