From 804af29ba07cceaa7835c86922814873d6731925 Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 25 Nov 2025 16:07:24 +0100 Subject: [PATCH 1/2] Remove unsupported SPANSTATUS.ERROR --- sentry_sdk/consts.py | 4 +--- sentry_sdk/integrations/anthropic.py | 4 ++-- sentry_sdk/integrations/google_genai/__init__.py | 8 ++++---- .../integrations/openai_agents/spans/execute_tool.py | 2 +- sentry_sdk/integrations/openai_agents/utils.py | 2 +- sentry_sdk/tracing.py | 3 +-- sentry_sdk/tracing_utils.py | 8 ++++---- 7 files changed, 14 insertions(+), 17 deletions(-) diff --git a/sentry_sdk/consts.py b/sentry_sdk/consts.py index 6faff402d2..3d719401fe 100644 --- a/sentry_sdk/consts.py +++ b/sentry_sdk/consts.py @@ -864,12 +864,11 @@ class SPANSTATUS: CANCELLED = "cancelled" DATA_LOSS = "data_loss" DEADLINE_EXCEEDED = "deadline_exceeded" - ERROR = "error" # OTel status code: https://opentelemetry.io/docs/concepts/signals/traces/#span-status FAILED_PRECONDITION = "failed_precondition" INTERNAL_ERROR = "internal_error" INVALID_ARGUMENT = "invalid_argument" NOT_FOUND = "not_found" - OK = "ok" # HTTP 200 and OTel status code: https://opentelemetry.io/docs/concepts/signals/traces/#span-status + OK = "ok" OUT_OF_RANGE = "out_of_range" PERMISSION_DENIED = "permission_denied" RESOURCE_EXHAUSTED = "resource_exhausted" @@ -877,7 +876,6 @@ class SPANSTATUS: UNAVAILABLE = "unavailable" UNIMPLEMENTED = "unimplemented" UNKNOWN_ERROR = "unknown_error" - UNSET = "unset" # OTel status code: https://opentelemetry.io/docs/concepts/signals/traces/#span-status class OP: diff --git a/sentry_sdk/integrations/anthropic.py b/sentry_sdk/integrations/anthropic.py index e252ab2424..232b6aab83 100644 --- a/sentry_sdk/integrations/anthropic.py +++ b/sentry_sdk/integrations/anthropic.py @@ -381,7 +381,7 @@ def _sentry_patched_create_sync(*args, **kwargs): return _execute_sync(f, *args, **kwargs) finally: span = sentry_sdk.get_current_span() - if span is not None and span.status == SPANSTATUS.ERROR: + if span is not None and span.status == SPANSTATUS.INTERNAL_ERROR: with capture_internal_exceptions(): span.__exit__(None, None, None) @@ -420,7 +420,7 @@ async def _sentry_patched_create_async(*args, **kwargs): return await _execute_async(f, *args, **kwargs) finally: span = sentry_sdk.get_current_span() - if span is not None and span.status == SPANSTATUS.ERROR: + if span is not None and span.status == SPANSTATUS.INTERNAL_ERROR: with capture_internal_exceptions(): span.__exit__(None, None, None) diff --git a/sentry_sdk/integrations/google_genai/__init__.py b/sentry_sdk/integrations/google_genai/__init__.py index 8f2d5df477..7f7873a119 100644 --- a/sentry_sdk/integrations/google_genai/__init__.py +++ b/sentry_sdk/integrations/google_genai/__init__.py @@ -107,7 +107,7 @@ def new_iterator(): yield chunk except Exception as exc: _capture_exception(exc) - chat_span.set_status(SPANSTATUS.ERROR) + chat_span.set_status(SPANSTATUS.INTERNAL_ERROR) raise finally: # Accumulate all chunks and set final response data on spans @@ -181,7 +181,7 @@ async def new_async_iterator(): yield chunk except Exception as exc: _capture_exception(exc) - chat_span.set_status(SPANSTATUS.ERROR) + chat_span.set_status(SPANSTATUS.INTERNAL_ERROR) raise finally: # Accumulate all chunks and set final response data on spans @@ -244,7 +244,7 @@ def new_generate_content(self, *args, **kwargs): response = f(self, *args, **kwargs) except Exception as exc: _capture_exception(exc) - chat_span.set_status(SPANSTATUS.ERROR) + chat_span.set_status(SPANSTATUS.INTERNAL_ERROR) raise set_span_data_for_response(chat_span, integration, response) @@ -290,7 +290,7 @@ async def new_async_generate_content(self, *args, **kwargs): response = await f(self, *args, **kwargs) except Exception as exc: _capture_exception(exc) - chat_span.set_status(SPANSTATUS.ERROR) + chat_span.set_status(SPANSTATUS.INTERNAL_ERROR) raise set_span_data_for_response(chat_span, integration, response) diff --git a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py index ad70762cd0..5f9e4cb340 100644 --- a/sentry_sdk/integrations/openai_agents/spans/execute_tool.py +++ b/sentry_sdk/integrations/openai_agents/spans/execute_tool.py @@ -42,7 +42,7 @@ def update_execute_tool_span(span, agent, tool, result): if isinstance(result, str) and result.startswith( "An error occurred while running the tool" ): - span.set_status(SPANSTATUS.ERROR) + span.set_status(SPANSTATUS.INTERNAL_ERROR) if should_send_default_pii(): span.set_data(SPANDATA.GEN_AI_TOOL_OUTPUT, result) diff --git a/sentry_sdk/integrations/openai_agents/utils.py b/sentry_sdk/integrations/openai_agents/utils.py index 125ff1175b..cc7c38553e 100644 --- a/sentry_sdk/integrations/openai_agents/utils.py +++ b/sentry_sdk/integrations/openai_agents/utils.py @@ -196,4 +196,4 @@ def _create_mcp_execute_tool_spans(span, result): SPANDATA.GEN_AI_TOOL_OUTPUT, output.output ) if output.error: - execute_tool_span.set_status(SPANSTATUS.ERROR) + execute_tool_span.set_status(SPANSTATUS.INTERNAL_ERROR) diff --git a/sentry_sdk/tracing.py b/sentry_sdk/tracing.py index 0d652e490a..7369afb420 100644 --- a/sentry_sdk/tracing.py +++ b/sentry_sdk/tracing.py @@ -408,8 +408,7 @@ def __enter__(self): def __exit__(self, ty, value, tb): # type: (Optional[Any], Optional[Any], Optional[Any]) -> None if value is not None and should_be_treated_as_error(ty, value): - if self.status != SPANSTATUS.ERROR: - self.set_status(SPANSTATUS.INTERNAL_ERROR) + self.set_status(SPANSTATUS.INTERNAL_ERROR) with capture_internal_exceptions(): scope, old_span = self._context_manager_state diff --git a/sentry_sdk/tracing_utils.py b/sentry_sdk/tracing_utils.py index 6506cca266..a71e0c3b2b 100644 --- a/sentry_sdk/tracing_utils.py +++ b/sentry_sdk/tracing_utils.py @@ -933,14 +933,14 @@ def get_current_span(scope=None): def set_span_errored(span=None): # type: (Optional[Span]) -> None """ - Set the status of the current or given span to ERROR. - Also sets the status of the transaction (root span) to ERROR. + Set the status of the current or given span to INTERNAL_ERROR. + Also sets the status of the transaction (root span) to INTERNAL_ERROR. """ span = span or get_current_span() if span is not None: - span.set_status(SPANSTATUS.ERROR) + span.set_status(SPANSTATUS.INTERNAL_ERROR) if span.containing_transaction is not None: - span.containing_transaction.set_status(SPANSTATUS.ERROR) + span.containing_transaction.set_status(SPANSTATUS.INTERNAL_ERROR) def _generate_sample_rand( From f0be3a9674e01beafb02e7642fd3ef2afe43779f Mon Sep 17 00:00:00 2001 From: Neel Shah Date: Tue, 25 Nov 2025 16:07:24 +0100 Subject: [PATCH 2/2] Remove unsupported SPANSTATUS.ERROR --- tests/integrations/anthropic/test_anthropic.py | 12 ++++++------ tests/integrations/cohere/test_cohere.py | 4 ++-- .../huggingface_hub/test_huggingface_hub.py | 6 +++--- tests/integrations/langchain/test_langchain.py | 4 ++-- tests/integrations/openai/test_openai.py | 4 ++-- .../integrations/openai_agents/test_openai_agents.py | 10 +++++----- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/integrations/anthropic/test_anthropic.py b/tests/integrations/anthropic/test_anthropic.py index f7c2d7e8a7..d4941ad0f4 100644 --- a/tests/integrations/anthropic/test_anthropic.py +++ b/tests/integrations/anthropic/test_anthropic.py @@ -701,7 +701,7 @@ def test_exception_message_create(sentry_init, capture_events): (event, transaction) = events assert event["level"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" def test_span_status_error(sentry_init, capture_events): @@ -722,8 +722,8 @@ def test_span_status_error(sentry_init, capture_events): (error, transaction) = events assert error["level"] == "error" - assert transaction["spans"][0]["tags"]["status"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["spans"][0]["tags"]["status"] == "internal_error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" @pytest.mark.asyncio @@ -745,8 +745,8 @@ async def test_span_status_error_async(sentry_init, capture_events): (error, transaction) = events assert error["level"] == "error" - assert transaction["spans"][0]["tags"]["status"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["spans"][0]["tags"]["status"] == "internal_error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" @pytest.mark.asyncio @@ -767,7 +767,7 @@ async def test_exception_message_create_async(sentry_init, capture_events): (event, transaction) = events assert event["level"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" def test_span_origin(sentry_init, capture_events): diff --git a/tests/integrations/cohere/test_cohere.py b/tests/integrations/cohere/test_cohere.py index a97d2befae..3d9ed0722e 100644 --- a/tests/integrations/cohere/test_cohere.py +++ b/tests/integrations/cohere/test_cohere.py @@ -181,8 +181,8 @@ def test_span_status_error(sentry_init, capture_events): (error, transaction) = events assert error["level"] == "error" - assert transaction["spans"][0]["tags"]["status"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["spans"][0]["tags"]["status"] == "internal_error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" @pytest.mark.parametrize( diff --git a/tests/integrations/huggingface_hub/test_huggingface_hub.py b/tests/integrations/huggingface_hub/test_huggingface_hub.py index ffeb6acbb5..e15c75cb6a 100644 --- a/tests/integrations/huggingface_hub/test_huggingface_hub.py +++ b/tests/integrations/huggingface_hub/test_huggingface_hub.py @@ -792,7 +792,7 @@ def test_chat_completion_api_error( assert span["op"] == "gen_ai.chat" assert span["description"] == "chat test-model" assert span["origin"] == "auto.ai.huggingface_hub" - assert span.get("tags", {}).get("status") == "error" + assert span.get("tags", {}).get("status") == "internal_error" assert ( error["contexts"]["trace"]["trace_id"] @@ -835,9 +835,9 @@ def test_span_status_error(sentry_init, capture_events, mock_hf_api_with_errors) assert sp["op"] == "http.client" assert span is not None - assert span["tags"]["status"] == "error" + assert span["tags"]["status"] == "internal_error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" @pytest.mark.httpx_mock(assert_all_requests_were_expected=False) diff --git a/tests/integrations/langchain/test_langchain.py b/tests/integrations/langchain/test_langchain.py index 59e9d719e4..d0d4e62941 100644 --- a/tests/integrations/langchain/test_langchain.py +++ b/tests/integrations/langchain/test_langchain.py @@ -347,8 +347,8 @@ def test_span_status_error(sentry_init, capture_events): (error, transaction) = events assert error["level"] == "error" - assert transaction["spans"][0]["tags"]["status"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["spans"][0]["tags"]["status"] == "internal_error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" def test_span_origin(sentry_init, capture_events): diff --git a/tests/integrations/openai/test_openai.py b/tests/integrations/openai/test_openai.py index febec5a80d..604480702f 100644 --- a/tests/integrations/openai/test_openai.py +++ b/tests/integrations/openai/test_openai.py @@ -440,8 +440,8 @@ def test_span_status_error(sentry_init, capture_events): (error, transaction) = events assert error["level"] == "error" - assert transaction["spans"][0]["tags"]["status"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["spans"][0]["tags"]["status"] == "internal_error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" @pytest.mark.asyncio diff --git a/tests/integrations/openai_agents/test_openai_agents.py b/tests/integrations/openai_agents/test_openai_agents.py index 6ff29271c3..46197ae855 100644 --- a/tests/integrations/openai_agents/test_openai_agents.py +++ b/tests/integrations/openai_agents/test_openai_agents.py @@ -724,8 +724,8 @@ async def test_span_status_error(sentry_init, capture_events, test_agent): (error, transaction) = events assert error["level"] == "error" - assert transaction["spans"][0]["tags"]["status"] == "error" - assert transaction["contexts"]["trace"]["status"] == "error" + assert transaction["spans"][0]["tags"]["status"] == "internal_error" + assert transaction["contexts"]["trace"]["status"] == "internal_error" @pytest.mark.asyncio @@ -827,7 +827,7 @@ async def test_mcp_tool_execution_spans(sentry_init, capture_events, test_agent) ) # Verify no error status since error was None - assert mcp_tool_span.get("tags", {}).get("status") != "error" + assert mcp_tool_span.get("tags", {}).get("status") != "internal_error" @pytest.mark.asyncio @@ -927,7 +927,7 @@ async def test_mcp_tool_execution_with_error(sentry_init, capture_events, test_a assert mcp_tool_span["data"]["gen_ai.tool.output"] is None # Verify error status was set - assert mcp_tool_span["tags"]["status"] == "error" + assert mcp_tool_span["tags"]["status"] == "internal_error" @pytest.mark.asyncio @@ -1218,4 +1218,4 @@ def failing_tool(message: str) -> str: # Verify error status was set (this is the key test for our patch) # The span should be marked as error because the tool execution failed - assert execute_tool_span["tags"]["status"] == "error" + assert execute_tool_span["tags"]["status"] == "internal_error"