fix(core): raise LLMEmptyResponseError for empty Anthropic responses (#9624)
* fix(core): raise LLMEmptyResponseError for empty Anthropic responses Fixes LET-7679: Opus 4.6 occasionally returns empty responses (no content and no tool calls), causing silent failures with stop_reason=end_turn. Changes: - Add LLMEmptyResponseError class (subclass of LLMServerError) - Raise error in anthropic_client for empty non-streaming responses - Raise error in anthropic_streaming_interface for empty streaming responses - Pass through LLMError instances in handle_llm_error to preserve specific types - Add test for empty streaming response detection This allows clients (letta-code) to catch this specific error and implement retry logic with cache-busting modifications. 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix(core): set invalid_llm_response stop reason for empty responses Catch LLMEmptyResponseError specifically and set stop_reason to invalid_llm_response instead of llm_api_error. This allows clients to distinguish empty responses from transient API errors. 🤖 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> --------- Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -19,6 +19,8 @@ from letta.errors import (
|
||||
LLMAuthenticationError,
|
||||
LLMBadRequestError,
|
||||
LLMConnectionError,
|
||||
LLMEmptyResponseError,
|
||||
LLMError,
|
||||
LLMInsufficientCreditsError,
|
||||
LLMNotFoundError,
|
||||
LLMPermissionDeniedError,
|
||||
@@ -957,6 +959,11 @@ class AnthropicClient(LLMClientBase):
|
||||
|
||||
@trace_method
|
||||
def handle_llm_error(self, e: Exception, llm_config: Optional[LLMConfig] = None) -> Exception:
|
||||
# Pass through errors that are already LLMError instances unchanged
|
||||
# This preserves specific error types like LLMEmptyResponseError
|
||||
if isinstance(e, LLMError):
|
||||
return e
|
||||
|
||||
is_byok = (llm_config.provider_category == ProviderCategory.byok) if llm_config else None
|
||||
|
||||
# make sure to check for overflow errors, regardless of error type
|
||||
@@ -1278,7 +1285,7 @@ class AnthropicClient(LLMClientBase):
|
||||
response.stop_reason,
|
||||
json.dumps(response_data),
|
||||
)
|
||||
raise LLMServerError(
|
||||
raise LLMEmptyResponseError(
|
||||
message=f"LLM provider returned empty content in response (ID: {response.id}, model: {response.model}, stop_reason: {response.stop_reason})",
|
||||
code=ErrorCode.INTERNAL_SERVER_ERROR,
|
||||
details={
|
||||
|
||||
Reference in New Issue
Block a user