diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/BaseResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/BaseResponseHandler.java index 56e994be86eb4..e2dff96c6ecb7 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/BaseResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/BaseResponseHandler.java @@ -95,7 +95,7 @@ public void validateResponse( protected abstract void checkForFailureStatusCode(Request request, HttpResult result); - private void checkForErrorObject(Request request, HttpResult result) { + protected void checkForErrorObject(Request request, HttpResult result) { var errorEntity = errorParseFunction.apply(result); if (errorEntity.errorStructureFound()) { @@ -116,12 +116,12 @@ protected Exception buildError(String message, Request request, HttpResult resul protected Exception buildError(String message, Request request, HttpResult result, ErrorResponse errorResponse) { var responseStatusCode = result.response().getStatusLine().getStatusCode(); return new ElasticsearchStatusException( - errorMessage(message, request, result, errorResponse, responseStatusCode), + constructErrorMessage(message, request, errorResponse, responseStatusCode), toRestStatus(responseStatusCode) ); } - protected String errorMessage(String message, Request request, HttpResult result, ErrorResponse errorResponse, int statusCode) { + public static String constructErrorMessage(String message, Request request, ErrorResponse errorResponse, int statusCode) { return (errorResponse == null || errorResponse.errorStructureFound() == false || Strings.isNullOrEmpty(errorResponse.getErrorMessage())) diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ChatCompletionErrorResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ChatCompletionErrorResponseHandler.java new file mode 100644 index 0000000000000..89617478f01c0 --- /dev/null +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ChatCompletionErrorResponseHandler.java @@ -0,0 +1,162 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.external.http.retry; + +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.xpack.core.inference.results.UnifiedChatCompletionException; +import org.elasticsearch.xpack.inference.external.http.HttpResult; +import org.elasticsearch.xpack.inference.external.request.Request; + +import java.util.Locale; +import java.util.Objects; + +import static org.elasticsearch.core.Strings.format; +import static org.elasticsearch.xpack.inference.external.http.retry.BaseResponseHandler.SERVER_ERROR_OBJECT; +import static org.elasticsearch.xpack.inference.external.http.retry.BaseResponseHandler.toRestStatus; + +public class ChatCompletionErrorResponseHandler { + private static final String STREAM_ERROR = "stream_error"; + + private final UnifiedChatCompletionErrorParser unifiedChatCompletionErrorParser; + + public ChatCompletionErrorResponseHandler(UnifiedChatCompletionErrorParser errorParser) { + this.unifiedChatCompletionErrorParser = Objects.requireNonNull(errorParser); + } + + public void checkForErrorObject(Request request, HttpResult result) { + var errorEntity = unifiedChatCompletionErrorParser.parse(result); + + if (errorEntity.errorStructureFound()) { + // We don't really know what happened because the status code was 200 so we'll return a failure and let the + // client retry if necessary + // If we did want to retry here, we'll need to determine if this was a streaming request, if it was + // we shouldn't retry because that would replay the entire streaming request and the client would get + // duplicate chunks back + throw new RetryException(false, buildChatCompletionErrorInternal(SERVER_ERROR_OBJECT, request, result, errorEntity)); + } + } + + public UnifiedChatCompletionException buildChatCompletionError(String message, Request request, HttpResult result) { + var errorResponse = unifiedChatCompletionErrorParser.parse(result); + return buildChatCompletionErrorInternal(message, request, result, errorResponse); + } + + private UnifiedChatCompletionException buildChatCompletionErrorInternal( + String message, + Request request, + HttpResult result, + UnifiedChatCompletionErrorResponse errorResponse + ) { + assert request.isStreaming() : "Only streaming requests support this format"; + var statusCode = result.response().getStatusLine().getStatusCode(); + var errorMessage = BaseResponseHandler.constructErrorMessage(message, request, errorResponse, statusCode); + var restStatus = toRestStatus(statusCode); + + if (errorResponse.errorStructureFound()) { + return new UnifiedChatCompletionException( + restStatus, + errorMessage, + errorResponse.type(), + errorResponse.code(), + errorResponse.param() + ); + } else { + return buildDefaultChatCompletionError(errorResponse, errorMessage, restStatus); + } + } + + /** + * Builds a default {@link UnifiedChatCompletionException} for a streaming request. + * This method is used when an error response is received we were unable to parse it in the format we were expecting. + * Only streaming requests should use this method. + * + * @param errorResponse the error response extracted from the HTTP result + * @param errorMessage the error message to include in the exception + * @param restStatus the REST status code of the response + * @return an instance of {@link UnifiedChatCompletionException} with details from the error response + */ + private static UnifiedChatCompletionException buildDefaultChatCompletionError( + ErrorResponse errorResponse, + String errorMessage, + RestStatus restStatus + ) { + return new UnifiedChatCompletionException( + restStatus, + errorMessage, + createErrorType(errorResponse), + restStatus.name().toLowerCase(Locale.ROOT) + ); + } + + /** + * Builds a mid-stream error for a streaming request. + * This method is used when an error occurs while processing a streaming response. + * Only streaming requests should use this method. + * + * @param inferenceEntityId the ID of the inference entity + * @param message the error message + * @param e the exception that caused the error, can be null + * @return a {@link UnifiedChatCompletionException} representing the mid-stream error + */ + public UnifiedChatCompletionException buildMidStreamChatCompletionError(String inferenceEntityId, String message, Exception e) { + var error = unifiedChatCompletionErrorParser.parse(message); + + if (error.errorStructureFound()) { + return new UnifiedChatCompletionException( + RestStatus.INTERNAL_SERVER_ERROR, + format( + "%s for request from inference entity id [%s]. Error message: [%s]", + SERVER_ERROR_OBJECT, + inferenceEntityId, + error.getErrorMessage() + ), + error.type(), + error.code(), + error.param() + ); + } else if (e != null) { + // If the error response does not match, we can still return an exception based on the original throwable + return UnifiedChatCompletionException.fromThrowable(e); + } else { + // If no specific error response is found, we return a default mid-stream error + return buildDefaultMidStreamChatCompletionError(inferenceEntityId, error); + } + } + + /** + * Builds a default mid-stream error for a streaming request. + * This method is used when no specific error response is found in the message. + * Only streaming requests should use this method. + * + * @param inferenceEntityId the ID of the inference entity + * @param errorResponse the error response extracted from the message + * @return a {@link UnifiedChatCompletionException} representing the default mid-stream error + */ + private static UnifiedChatCompletionException buildDefaultMidStreamChatCompletionError( + String inferenceEntityId, + ErrorResponse errorResponse + ) { + return new UnifiedChatCompletionException( + RestStatus.INTERNAL_SERVER_ERROR, + format("%s for request from inference entity id [%s]", SERVER_ERROR_OBJECT, inferenceEntityId), + createErrorType(errorResponse), + STREAM_ERROR + ); + } + + /** + * Creates a string representation of the error type based on the provided ErrorResponse. + * This method is used to generate a human-readable error type for logging or exception messages. + * + * @param errorResponse the ErrorResponse object + * @return a string representing the error type + */ + private static String createErrorType(ErrorResponse errorResponse) { + return errorResponse != null ? errorResponse.getClass().getSimpleName() : "unknown"; + } +} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ErrorResponse.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ErrorResponse.java index 7fc272931e7fb..a692f4de4fca2 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ErrorResponse.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/ErrorResponse.java @@ -22,7 +22,7 @@ public ErrorResponse(String errorMessage) { this.errorStructureFound = true; } - private ErrorResponse(boolean errorStructureFound) { + protected ErrorResponse(boolean errorStructureFound) { this.errorMessage = ""; this.errorStructureFound = errorStructureFound; } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/UnifiedChatCompletionErrorParser.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/UnifiedChatCompletionErrorParser.java new file mode 100644 index 0000000000000..60f1c44919ca9 --- /dev/null +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/UnifiedChatCompletionErrorParser.java @@ -0,0 +1,16 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.external.http.retry; + +import org.elasticsearch.xpack.inference.external.http.HttpResult; + +public interface UnifiedChatCompletionErrorParser { + UnifiedChatCompletionErrorResponse parse(HttpResult result); + + UnifiedChatCompletionErrorResponse parse(String result); +} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/UnifiedChatCompletionErrorResponse.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/UnifiedChatCompletionErrorResponse.java new file mode 100644 index 0000000000000..3a70842455f1d --- /dev/null +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/external/http/retry/UnifiedChatCompletionErrorResponse.java @@ -0,0 +1,63 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.inference.external.http.retry; + +import org.elasticsearch.core.Nullable; + +import java.util.Objects; + +public class UnifiedChatCompletionErrorResponse extends ErrorResponse { + public static final UnifiedChatCompletionErrorResponse UNDEFINED_ERROR = new UnifiedChatCompletionErrorResponse(); + + @Nullable + private final String code; + @Nullable + private final String param; + private final String type; + + public UnifiedChatCompletionErrorResponse(String errorMessage, String type, @Nullable String code, @Nullable String param) { + super(errorMessage); + this.code = code; + this.param = param; + this.type = Objects.requireNonNull(type); + } + + private UnifiedChatCompletionErrorResponse() { + super(false); + this.code = null; + this.param = null; + this.type = "unknown"; + } + + @Nullable + public String code() { + return code; + } + + @Nullable + public String param() { + return param; + } + + public String type() { + return type; + } + + @Override + public boolean equals(Object o) { + if (o == null || getClass() != o.getClass()) return false; + if (super.equals(o) == false) return false; + UnifiedChatCompletionErrorResponse that = (UnifiedChatCompletionErrorResponse) o; + return Objects.equals(code, that.code) && Objects.equals(param, that.param) && Objects.equals(type, that.type); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), code, param, type); + } +} diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elastic/ElasticInferenceServiceUnifiedChatCompletionResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elastic/ElasticInferenceServiceUnifiedChatCompletionResponseHandler.java index ad40d43b3af3b..f45d390b404d4 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elastic/ElasticInferenceServiceUnifiedChatCompletionResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elastic/ElasticInferenceServiceUnifiedChatCompletionResponseHandler.java @@ -49,7 +49,7 @@ protected Exception buildError(String message, Request request, HttpResult resul var restStatus = toRestStatus(responseStatusCode); return new UnifiedChatCompletionException( restStatus, - errorMessage(message, request, result, errorResponse, responseStatusCode), + constructErrorMessage(message, request, errorResponse, responseStatusCode), "error", restStatus.name().toLowerCase(Locale.ROOT) ); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiUnifiedChatCompletionResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiUnifiedChatCompletionResponseHandler.java index 9e6fdb6eb8bb5..56969c3390268 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiUnifiedChatCompletionResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiUnifiedChatCompletionResponseHandler.java @@ -10,9 +10,6 @@ import org.elasticsearch.common.Strings; import org.elasticsearch.core.Nullable; import org.elasticsearch.inference.InferenceServiceResults; -import org.elasticsearch.logging.LogManager; -import org.elasticsearch.logging.Logger; -import org.elasticsearch.rest.RestStatus; import org.elasticsearch.xcontent.ConstructingObjectParser; import org.elasticsearch.xcontent.ParseField; import org.elasticsearch.xcontent.XContentFactory; @@ -22,29 +19,31 @@ import org.elasticsearch.xpack.core.inference.results.StreamingUnifiedChatCompletionResults; import org.elasticsearch.xpack.core.inference.results.UnifiedChatCompletionException; import org.elasticsearch.xpack.inference.external.http.HttpResult; -import org.elasticsearch.xpack.inference.external.http.retry.ErrorResponse; +import org.elasticsearch.xpack.inference.external.http.retry.ChatCompletionErrorResponseHandler; +import org.elasticsearch.xpack.inference.external.http.retry.UnifiedChatCompletionErrorParser; +import org.elasticsearch.xpack.inference.external.http.retry.UnifiedChatCompletionErrorResponse; import org.elasticsearch.xpack.inference.external.request.Request; import org.elasticsearch.xpack.inference.external.response.streaming.ServerSentEventParser; import org.elasticsearch.xpack.inference.external.response.streaming.ServerSentEventProcessor; import org.elasticsearch.xpack.inference.services.googlevertexai.response.GoogleVertexAiCompletionResponseEntity; import java.nio.charset.StandardCharsets; -import java.util.Locale; -import java.util.Objects; import java.util.Optional; import java.util.concurrent.Flow; -import static org.elasticsearch.core.Strings.format; - public class GoogleVertexAiUnifiedChatCompletionResponseHandler extends GoogleVertexAiResponseHandler { private static final String ERROR_FIELD = "error"; private static final String ERROR_CODE_FIELD = "code"; private static final String ERROR_MESSAGE_FIELD = "message"; private static final String ERROR_STATUS_FIELD = "status"; + private static final GoogleVertexAiErrorParser ERROR_PARSER = new GoogleVertexAiErrorParser(); + + private final ChatCompletionErrorResponseHandler chatCompletionErrorResponseHandler; public GoogleVertexAiUnifiedChatCompletionResponseHandler(String requestType) { super(requestType, GoogleVertexAiCompletionResponseEntity::fromResponse, GoogleVertexAiErrorResponse::fromResponse, true); + this.chatCompletionErrorResponseHandler = new ChatCompletionErrorResponseHandler(ERROR_PARSER); } @Override @@ -52,7 +51,9 @@ public InferenceServiceResults parseResult(Request request, Flow.Publisher buildMidStreamError(request, m, e)); + var googleVertexAiProcessor = new GoogleVertexAiUnifiedStreamingProcessor( + (m, e) -> chatCompletionErrorResponseHandler.buildMidStreamChatCompletionError(request.getInferenceEntityId(), m, e) + ); flow.subscribe(serverSentEventProcessor); serverSentEventProcessor.subscribe(googleVertexAiProcessor); @@ -60,63 +61,35 @@ public InferenceServiceResults parseResult(Request request, Flow.Publisher, Void> ERROR_PARSER = new ConstructingObjectParser<>( - "google_vertex_ai_error_wrapper", - true, - args -> Optional.ofNullable((GoogleVertexAiErrorResponse) args[0]) - ); + public static class GoogleVertexAiErrorResponse extends UnifiedChatCompletionErrorResponse { + private static final ConstructingObjectParser, Void> ERROR_PARSER = + new ConstructingObjectParser<>( + "google_vertex_ai_error_wrapper", + true, + args -> Optional.ofNullable((GoogleVertexAiErrorResponse) args[0]) + ); private static final ConstructingObjectParser ERROR_BODY_PARSER = new ConstructingObjectParser<>( "google_vertex_ai_error_body", @@ -137,46 +110,39 @@ public static class GoogleVertexAiErrorResponse extends ErrorResponse { ); } - public static ErrorResponse fromResponse(HttpResult response) { + public static UnifiedChatCompletionErrorResponse fromResponse(HttpResult response) { try ( XContentParser parser = XContentFactory.xContent(XContentType.JSON) .createParser(XContentParserConfiguration.EMPTY, response.body()) ) { - return ERROR_PARSER.apply(parser, null).orElse(ErrorResponse.UNDEFINED_ERROR); + return ERROR_PARSER.apply(parser, null).orElse(UnifiedChatCompletionErrorResponse.UNDEFINED_ERROR); } catch (Exception e) { var resultAsString = new String(response.body(), StandardCharsets.UTF_8); - return new ErrorResponse(Strings.format("Unable to parse the Google Vertex AI error, response body: [%s]", resultAsString)); + return new GoogleVertexAiErrorResponse( + Strings.format("Unable to parse the Google Vertex AI error, response body: [%s]", resultAsString) + ); } } - static ErrorResponse fromString(String response) { + static UnifiedChatCompletionErrorResponse fromString(String response) { try ( XContentParser parser = XContentFactory.xContent(XContentType.JSON) .createParser(XContentParserConfiguration.EMPTY, response) ) { - return ERROR_PARSER.apply(parser, null).orElse(ErrorResponse.UNDEFINED_ERROR); + return ERROR_PARSER.apply(parser, null).orElse(UnifiedChatCompletionErrorResponse.UNDEFINED_ERROR); } catch (Exception e) { - return new ErrorResponse(Strings.format("Unable to parse the Google Vertex AI error, response body: [%s]", response)); + return new GoogleVertexAiErrorResponse( + Strings.format("Unable to parse the Google Vertex AI error, response body: [%s]", response) + ); } } - private final int code; - @Nullable - private final String status; - - GoogleVertexAiErrorResponse(Integer code, String errorMessage, @Nullable String status) { - super(Objects.requireNonNull(errorMessage)); - this.code = code == null ? 0 : code; - this.status = status; - } - - public int code() { - return code; + GoogleVertexAiErrorResponse(@Nullable Integer code, String errorMessage, @Nullable String status) { + super(errorMessage, status != null ? status : "google_vertex_ai_error", code == null ? "0" : String.valueOf(code), null); } - @Nullable - public String status() { - return status != null ? status : "google_vertex_ai_error"; + GoogleVertexAiErrorResponse(String errorMessage) { + super(errorMessage, "google_vertex_ai_error", null, null); } } } diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/huggingface/HuggingFaceChatCompletionResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/huggingface/HuggingFaceChatCompletionResponseHandler.java index 8dffd612db5c8..8b8deaef3279d 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/huggingface/HuggingFaceChatCompletionResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/huggingface/HuggingFaceChatCompletionResponseHandler.java @@ -45,7 +45,7 @@ protected Exception buildError(String message, Request request, HttpResult resul assert request.isStreaming() : "Only streaming requests support this format"; var responseStatusCode = result.response().getStatusLine().getStatusCode(); if (request.isStreaming()) { - var errorMessage = errorMessage(message, request, result, errorResponse, responseStatusCode); + var errorMessage = constructErrorMessage(message, request, errorResponse, responseStatusCode); var restStatus = toRestStatus(responseStatusCode); return errorResponse instanceof HuggingFaceErrorResponseEntity ? new UnifiedChatCompletionException( diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonUnifiedChatCompletionResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonUnifiedChatCompletionResponseHandler.java index 41b82bbf2cd02..570dbd1e709ee 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonUnifiedChatCompletionResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonUnifiedChatCompletionResponseHandler.java @@ -34,7 +34,7 @@ protected Exception buildError(String message, Request request, HttpResult resul assert request.isStreaming() : "Only streaming requests support this format"; var responseStatusCode = result.response().getStatusLine().getStatusCode(); if (request.isStreaming()) { - var errorMessage = errorMessage(message, request, result, errorResponse, responseStatusCode); + var errorMessage = constructErrorMessage(message, request, errorResponse, responseStatusCode); var restStatus = toRestStatus(responseStatusCode); return errorResponse instanceof IbmWatsonxErrorResponseEntity ? new UnifiedChatCompletionException(restStatus, errorMessage, WATSONX_ERROR, restStatus.name().toLowerCase(Locale.ROOT)) diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/mistral/MistralUnifiedChatCompletionResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/mistral/MistralUnifiedChatCompletionResponseHandler.java index a9d6df687fe99..cbff01c6227eb 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/mistral/MistralUnifiedChatCompletionResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/mistral/MistralUnifiedChatCompletionResponseHandler.java @@ -34,7 +34,7 @@ protected Exception buildError(String message, Request request, HttpResult resul assert request.isStreaming() : "Only streaming requests support this format"; var responseStatusCode = result.response().getStatusLine().getStatusCode(); if (request.isStreaming()) { - var errorMessage = errorMessage(message, request, result, errorResponse, responseStatusCode); + var errorMessage = constructErrorMessage(message, request, errorResponse, responseStatusCode); var restStatus = toRestStatus(responseStatusCode); return errorResponse instanceof MistralErrorResponse ? new UnifiedChatCompletionException(restStatus, errorMessage, MISTRAL_ERROR, restStatus.name().toLowerCase(Locale.ROOT)) diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/openai/OpenAiUnifiedChatCompletionResponseHandler.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/openai/OpenAiUnifiedChatCompletionResponseHandler.java index e1a0117c7bcca..8a70f4428799b 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/openai/OpenAiUnifiedChatCompletionResponseHandler.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/openai/OpenAiUnifiedChatCompletionResponseHandler.java @@ -56,7 +56,7 @@ protected Exception buildError(String message, Request request, HttpResult resul assert request.isStreaming() : "Only streaming requests support this format"; var responseStatusCode = result.response().getStatusLine().getStatusCode(); if (request.isStreaming()) { - var errorMessage = errorMessage(message, request, result, errorResponse, responseStatusCode); + var errorMessage = constructErrorMessage(message, request, errorResponse, responseStatusCode); var restStatus = toRestStatus(responseStatusCode); return errorResponse instanceof StreamingErrorResponse oer ? new UnifiedChatCompletionException(restStatus, errorMessage, oer.type(), oer.code(), oer.param())