fix(core): handle protocol errors and foreign key violations (#9308)
* fix(core): handle PermissionDeniedError in provider API key validation Fixed OpenAI PermissionDeniedError being raised as unknown error when validating provider API keys. The check_api_key methods in OpenAI-based providers (OpenAI, OpenRouter, Azure, Together) now properly catch and re-raise PermissionDeniedError as LLMPermissionDeniedError. 🐛 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix(core): handle Unicode surrogates in OpenAI requests Sanitize invalid UTF-16 surrogates before sending requests to OpenAI API. Fixes UnicodeEncodeError when message content contains unpaired surrogates from corrupted emoji data or malformed Unicode sequences. 🐾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix(core): handle MCP tool schema validation errors gracefully Catch fastmcp.exceptions.ToolError in execute_mcp_tool endpoint and convert to LettaInvalidArgumentError (400) instead of letting it propagate as 500 error. This is an expected user error when tool arguments don't match the MCP tool's schema. Fixes Datadog issue 8f2d874a-f8e5-11f0-9b25-da7ad0900000 🐾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix(core): handle ExceptionGroup-wrapped ToolError in MCP executor When MCP tools fail with validation errors (e.g., missing required parameters), fastmcp raises ToolError exceptions that may be wrapped in ExceptionGroup by Python's async TaskGroup. The exception handler now unwraps single-exception groups before checking if the error should be handled gracefully. Fixes Calendly API "organization parameter missing" errors being logged to Datadog instead of returning friendly error messages to users. 🐾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta <noreply@letta.com> * fix: handle missing agent in create_conversation to prevent foreign key violation * Update .gitignore --------- Co-authored-by: Letta <noreply@letta.com>
This commit is contained in:
@@ -67,6 +67,33 @@ from letta.settings import model_settings
|
||||
logger = get_logger(__name__)
|
||||
|
||||
|
||||
def sanitize_unicode_surrogates(obj: Any) -> Any:
|
||||
"""Recursively sanitize invalid Unicode surrogates in strings within nested data structures.
|
||||
|
||||
This fixes UnicodeEncodeError when the OpenAI SDK tries to encode requests containing
|
||||
unpaired UTF-16 surrogates (e.g., '\ud83c' without its pair) which can occur in corrupted
|
||||
emoji data or malformed Unicode sequences.
|
||||
|
||||
Args:
|
||||
obj: The object to sanitize (dict, list, str, or other types)
|
||||
|
||||
Returns:
|
||||
The sanitized object with invalid surrogates replaced by the Unicode replacement character
|
||||
"""
|
||||
if isinstance(obj, dict):
|
||||
return {k: sanitize_unicode_surrogates(v) for k, v in obj.items()}
|
||||
elif isinstance(obj, list):
|
||||
return [sanitize_unicode_surrogates(item) for item in obj]
|
||||
elif isinstance(obj, str):
|
||||
try:
|
||||
obj.encode("utf-8")
|
||||
return obj
|
||||
except UnicodeEncodeError:
|
||||
return obj.encode("utf-8", errors="replace").decode("utf-8")
|
||||
else:
|
||||
return obj
|
||||
|
||||
|
||||
def is_openai_reasoning_model(model: str) -> bool:
|
||||
"""Utility function to check if the model is a 'reasoner'"""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user