alibaba/spring-ai-alibaba · error · RuntimeException

搜索请求执行失败

Error message

搜索请求执行失败

What it means

ElasticsearchClientWrapper.search() delegates to elasticsearchClient.search() and wraps any IOException in a RuntimeException "搜索请求执行失败" ("Search request execution failed"). IOExceptions here indicate the request could not reach the cluster or the connection broke mid-request — not query-syntax problems, which surface as Elasticsearch API errors instead.

Source

Thrown at spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-start/src/main/java/com/alibaba/cloud/ai/studio/admin/repository/impl/ElasticsearchClientWrapper.java:32

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
@RequiredArgsConstructor
@Slf4j
public class ElasticsearchClientWrapper {

    private final ElasticsearchClient elasticsearchClient;

    /**
     * 执行搜索查询
     */
    public SearchResponse<Map> search(String index, SearchRequest searchRequest) {
        try {
            return elasticsearchClient.search(searchRequest, Map.class);
        } catch (IOException e) {
            throw new RuntimeException("搜索请求执行失败", e);
        }
    }

    /**
     * 批量索引文档
     */
    public void bulkIndex(String index, List<Map<String, Object>> documents) {
        try {
            BulkRequest.Builder bulkBuilder = new BulkRequest.Builder();
            
            for (Map<String, Object> doc : documents) {
                bulkBuilder.operations(op -> op
                    .index(idx -> idx
                        .index(index)
                        .document(doc)
                    )
                );
            }

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Inspect the wrapped IOException cause (ConnectException, SocketTimeoutException, etc.) to identify the network problem.
  2. Verify the ES cluster is up and reachable from the app host (curl http://host:9200/_cluster/health).
  3. Check for connection-pool saturation and tune maxConnTotal/maxConnPerRoute.
  4. Add retry logic with backoff for transient IO failures, or use the low-level RestClient's built-in failure listener/retry.
  5. Ensure keep-alive/idle connection settings match the LB/firewall timeout.

Example fix

// before
catch (IOException e) { throw new RuntimeException("搜索请求执行失败", e); }
// after
catch (IOException e) {
    if (e instanceof java.net.ConnectException) { /* mark node unhealthy, retry other node */ }
    throw new RuntimeException("搜索请求执行失败: " + e.getMessage(), e);
}
Defensive patterns

Strategy: retry

Validate before calling

// before querying
try (var sock = new Socket()) { sock.connect(new InetSocketAddress(host, 9200), 2000); }

Try / catch

try { return wrapper.search(index, req); }
catch (RuntimeException e) {
    Throwable c = e.getCause();
    if (c instanceof IOException && isTransient(c)) { return retryWithBackoff(() -> wrapper.search(index, req), 3); }
    throw e;
}

Prevention

When it happens

Trigger: Calling search(index, searchRequest) when the Elasticsearch node is down, the connection is refused/timed out, the socket is reset, or DNS resolution fails while executing the search request.

Common situations: ES cluster restart during a request; network partition or firewall dropping port 9200; connection-pool exhaustion from a load spike; stale keep-alive connections after idle periods.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/fc4c5a7dda7c64e8. Report an issue: GitHub.