Skip to content
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 7 additions & 14 deletions sentry_sdk/integrations/strawberry.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,34 +181,27 @@
event_processor = _make_request_event_processor(self.execution_context)
scope.add_event_processor(event_processor)

span = sentry_sdk.get_current_span()
if span:
self.graphql_span = span.start_child(
op=op,
name=description,
origin=StrawberryIntegration.origin,
)
else:
self.graphql_span = sentry_sdk.start_span(
op=op,
name=description,
origin=StrawberryIntegration.origin,
)
self.graphql_span = sentry_sdk.start_span(
op=op,
name=description,
origin=StrawberryIntegration.origin,
)
self.graphql_span.__enter__()

self.graphql_span.set_data("graphql.operation.type", operation_type)
self.graphql_span.set_data("graphql.operation.name", self._operation_name)
self.graphql_span.set_data("graphql.document", self.execution_context.query)
self.graphql_span.set_data("graphql.resource_name", self._resource_name)

yield

transaction = self.graphql_span.containing_transaction
if transaction and self.execution_context.operation_name:
transaction.name = self.execution_context.operation_name
transaction.source = TransactionSource.COMPONENT
transaction.op = op

self.graphql_span.finish()
self.graphql_span.__exit__(None, None, None)

Check warning on line 204 in sentry_sdk/integrations/strawberry.py

View check run for this annotation

@sentry/warden / warden: find-bugs

Exception status not propagated to span when GraphQL operation fails

The new code calls `self.graphql_span.__exit__(None, None, None)` unconditionally, which tells the span that no exception occurred. In the `Span.__exit__` method (tracing.py:399-400), exceptions are detected via the `value` parameter and result in setting the span status to `INTERNAL_ERROR`. By always passing `None`, exceptions raised during GraphQL operations will not be reflected in the span's status, losing important error context for observability.

Check warning on line 204 in sentry_sdk/integrations/strawberry.py

View workflow job for this annotation

GitHub Actions / warden: find-bugs

Span.__exit__ always called with None arguments, preventing error status on exceptions

The `Span.__exit__` method checks if `value is not None` to set `SPANSTATUS.INTERNAL_ERROR` on the span when an exception occurs. By always calling `self.graphql_span.__exit__(None, None, None)`, exceptions that occur during GraphQL operations won't mark the span as errored. This means error tracking for GraphQL operations loses exception context that the Span class is designed to capture.

Check warning on line 204 in sentry_sdk/integrations/strawberry.py

View check run for this annotation

@sentry/warden / warden: code-review

Span not closed if exception thrown into generator

The manual `__enter__()` and `__exit__(None, None, None)` calls lack exception safety. If an exception is thrown into the generator at the `yield` point, the code after `yield` (including `__exit__`) won't execute, leaving the span unclosed and the scope in an inconsistent state (scope.span still points to this span). Additionally, always passing `(None, None, None)` to `__exit__` means any exception that does reach that code won't be recorded on the span's status.

Check warning on line 204 in sentry_sdk/integrations/strawberry.py

View workflow job for this annotation

GitHub Actions / warden: code-review

Span context manager not properly cleaned up when exception occurs at yield

The `__enter__()` call at line 189 sets `scope.span = self.graphql_span` and stores the previous span for restoration. However, if an exception is thrown at the `yield` point (line 196), the code after yield including `__exit__()` (line 204) will not execute. This leaves the scope in a corrupted state where `scope.span` still points to the graphql_span, and the span is never finished. The old code used `finish()` which also wouldn't run on exception, but it didn't call `__enter__()` to modify scope, so no scope corruption occurred.
Comment thread
sentrivana marked this conversation as resolved.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing try/finally around yield leaks scope state

Medium Severity

__enter__() modifies scope.span and stores the old span in _context_manager_state, but the yield between __enter__() and __exit__() is not wrapped in a try/finally. If the Strawberry framework throws an exception into the generator or calls close() on it, the code after yield (including __exit__) is never reached. This leaves scope.span permanently pointing to the now-stale graphql_span, and the previous span is never restored. The old code using finish() didn't have this issue because it never called __enter__() and therefore never modified scope state.

Fix in Cursor Fix in Web


def on_validate(self) -> "Generator[None, None, None]":
self.validation_span = self.graphql_span.start_child(
Expand Down
Loading