From f97d758afdde4422fa6eedde7bd97f925c85826e Mon Sep 17 00:00:00 2001 From: extio-de Date: Sun, 10 May 2026 18:46:30 +0200 Subject: [PATCH] feat: Enhance error handling by introducing ErrorResponse class and updating logErrorResponse method --- .../oai/completion/AbstractCompletionClient.java | 16 +++++++++------- .../client/oai/completion/ErrorResponse.java | 10 ++++++++++ .../completion/chat/ChatCompletionClient.java | 6 ++++-- .../completion/text/TextCompletionClient.java | 6 ++++-- .../extio/lmlib/client/ollama/OllamaClient.java | 2 +- .../client/openrouter/OpenRouterClient.java | 9 --------- 6 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 src/main/java/de/extio/lmlib/client/oai/completion/ErrorResponse.java diff --git a/src/main/java/de/extio/lmlib/client/oai/completion/AbstractCompletionClient.java b/src/main/java/de/extio/lmlib/client/oai/completion/AbstractCompletionClient.java index 1073650..d99db7c 100755 --- a/src/main/java/de/extio/lmlib/client/oai/completion/AbstractCompletionClient.java +++ b/src/main/java/de/extio/lmlib/client/oai/completion/AbstractCompletionClient.java @@ -1,7 +1,5 @@ package de.extio.lmlib.client.oai.completion; -import java.io.IOException; -import java.io.InputStream; import java.math.BigDecimal; import java.text.DecimalFormat; import java.time.Duration; @@ -19,12 +17,12 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatusCode; import org.springframework.web.client.RestClient; import org.springframework.web.client.RestClientException; import org.springframework.web.client.RestClientResponseException; import com.fasterxml.jackson.annotation.JsonInclude; +import tools.jackson.core.JacksonException; import tools.jackson.core.json.JsonReadFeature; import tools.jackson.databind.DeserializationFeature; import tools.jackson.databind.ObjectMapper; @@ -171,13 +169,17 @@ public abstract class AbstractCompletionClient implements Client, DisposableBean return this.getModelNames(modelProfile, false).stream().findFirst().orElse(""); } - protected void logErrorResponse(final HttpStatusCode statusCode, final InputStream responseBody) { + protected String getErrorMessage(final String errorBody) { try { - LOGGER.warn("Error response from server: {} {}", statusCode, new String(responseBody.readAllBytes(), java.nio.charset.StandardCharsets.UTF_8)); + final var errorResponse = this.objectMapper.readValue(errorBody, ErrorResponse.class); + if (errorResponse != null && errorResponse.error() != null && errorResponse.error().message() != null && !errorResponse.error().message().isBlank()) { + return errorResponse.error().message(); + } } - catch (final IOException e) { - LOGGER.warn("Error response from server: {} ", statusCode, e.getMessage()); + catch (final JacksonException e) { + LOGGER.debug("Failed to parse error response body", e); } + return errorBody; } private List loadModelNames(final ModelProfile modelProfile) { diff --git a/src/main/java/de/extio/lmlib/client/oai/completion/ErrorResponse.java b/src/main/java/de/extio/lmlib/client/oai/completion/ErrorResponse.java new file mode 100644 index 0000000..d844e2e --- /dev/null +++ b/src/main/java/de/extio/lmlib/client/oai/completion/ErrorResponse.java @@ -0,0 +1,10 @@ +package de.extio.lmlib.client.oai.completion; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public record ErrorResponse(@JsonProperty("error") ErrorMessage error) { + + public record ErrorMessage(@JsonProperty("message") String message) { + + } +} diff --git a/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java b/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java index 8cba38d..19bb5b8 100755 --- a/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java +++ b/src/main/java/de/extio/lmlib/client/oai/completion/chat/ChatCompletionClient.java @@ -81,8 +81,10 @@ public class ChatCompletionClient extends AbstractCompletionClient { .body(requestBody) .exchange((clientRequest, clientResponse) -> { if (clientResponse.getStatusCode().isError()) { - this.logErrorResponse(clientResponse.getStatusCode(), clientResponse.getBody()); - throw new IllegalStateException("Error response from server: " + clientResponse.getStatusCode()); + final var errorBody = new String(clientResponse.getBody().readAllBytes(), StandardCharsets.UTF_8); + final var errorMessage = this.getErrorMessage(errorBody); + LOGGER.warn("Error response from server: {} {}", clientResponse.getStatusCode(), errorMessage); + throw new IllegalStateException("Error response from server: " + clientResponse.getStatusCode() + " " + errorMessage); } if (chunkConsumer == null) { diff --git a/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java b/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java index ad6c1cf..538d76d 100755 --- a/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java +++ b/src/main/java/de/extio/lmlib/client/oai/completion/text/TextCompletionClient.java @@ -83,8 +83,10 @@ public class TextCompletionClient extends AbstractCompletionClient { .body(requestBody) .exchange((clientRequest, clientResponse) -> { if (clientResponse.getStatusCode().isError()) { - this.logErrorResponse(clientResponse.getStatusCode(), clientResponse.getBody()); - throw new IllegalStateException("Error response from server: " + clientResponse.getStatusCode()); + final var errorBody = new String(clientResponse.getBody().readAllBytes(), StandardCharsets.UTF_8); + final var errorMessage = this.getErrorMessage(errorBody); + LOGGER.warn("Error response from server: {} {}", clientResponse.getStatusCode(), errorMessage); + throw new IllegalStateException("Error response from server: " + clientResponse.getStatusCode() + " " + errorMessage); } if (chunkConsumer == null) { diff --git a/src/main/java/de/extio/lmlib/client/ollama/OllamaClient.java b/src/main/java/de/extio/lmlib/client/ollama/OllamaClient.java index 641dc70..1917c9c 100644 --- a/src/main/java/de/extio/lmlib/client/ollama/OllamaClient.java +++ b/src/main/java/de/extio/lmlib/client/ollama/OllamaClient.java @@ -130,7 +130,7 @@ public class OllamaClient implements Client { .exchange((clientRequest, clientResponse) -> { if (clientResponse.getStatusCode().isError()) { this.logErrorResponse(clientResponse.getStatusCode(), clientResponse.getBody()); - throw new IllegalStateException("Error response from server: " + clientResponse.getStatusCode()); + throw new IllegalStateException("Error response from server: " + clientResponse.getStatusCode() + " " + clientResponse.getBody()); } if (chunkConsumer == null) { final var ollamaResponse = this.objectMapper.readValue(clientResponse.getBody(), OllamaChatResponse.class); diff --git a/src/main/java/de/extio/lmlib/client/openrouter/OpenRouterClient.java b/src/main/java/de/extio/lmlib/client/openrouter/OpenRouterClient.java index 4db916d..d75793c 100644 --- a/src/main/java/de/extio/lmlib/client/openrouter/OpenRouterClient.java +++ b/src/main/java/de/extio/lmlib/client/openrouter/OpenRouterClient.java @@ -106,15 +106,6 @@ public class OpenRouterClient extends ChatCompletionClient { return metadata == null ? OpenAiProviderDialect.ChatTokenLimitParameterMode.MAX_COMPLETION_TOKENS : metadata.tokenLimitParameterMode(); } - @Override - protected OpenAiProviderDialect.ReasoningEffort reasoningEffort(final ModelProfile modelProfile) { - if (!this.sendReasoning(modelProfile)) { - return null; - } - final var reasoningEffort = super.reasoningEffort(modelProfile); - return reasoningEffort == null ? OpenAiProviderDialect.ReasoningEffort.MEDIUM : reasoningEffort; - } - private OpenRouterModelDiscovery.ResolvedOpenRouterModelMetadata resolveMetadata(final ModelProfile modelProfile) { if (modelProfile == null || modelProfile.modelProvider() != ModelProvider.OPENROUTER) { return null;