From 24e51f611c4023adafe30b538f3cb126ee858f1f Mon Sep 17 00:00:00 2001 From: cthomas Date: Tue, 3 Feb 2026 13:18:36 -0800 Subject: [PATCH] fix: check for actual error content in ClickHouse traces (#9260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fix: check for actual error content, not just "error" key presence OpenAI Responses API returns {"error": null} on success, which incorrectly triggered is_error=True. Now we check if error_data is truthy rather than just checking key existence. 🤖 Generated with [Letta Code](https://letta.com) Co-authored-by: Letta --- .../services/provider_trace_backends/clickhouse.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/letta/services/provider_trace_backends/clickhouse.py b/letta/services/provider_trace_backends/clickhouse.py index 6b3c286b..3f5f842e 100644 --- a/letta/services/provider_trace_backends/clickhouse.py +++ b/letta/services/provider_trace_backends/clickhouse.py @@ -99,18 +99,17 @@ class ClickhouseProviderTraceBackend(ProviderTraceBackendClient): # Extract usage from response (generic parsing for common formats) usage = self._extract_usage(provider_trace.response_json, provider) - # Check for error in response - is_error = "error" in provider_trace.response_json - error_type = None + # Check for error in response - must have actual error content, not just null + # OpenAI Responses API returns {"error": null} on success + error_data = provider_trace.response_json.get("error") + error_type = provider_trace.response_json.get("error_type") error_message = None + is_error = bool(error_data) or bool(error_type) if is_error: - # error_type may be at top level or inside error dict - error_type = provider_trace.response_json.get("error_type") - error_data = provider_trace.response_json.get("error", {}) if isinstance(error_data, dict): error_type = error_type or error_data.get("type") error_message = error_data.get("message", str(error_data))[:1000] - else: + elif error_data: error_message = str(error_data)[:1000] # Extract UUID from provider_trace.id (strip "provider_trace-" prefix)