Skip to content
Merged
Show file tree
Hide file tree
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
18 changes: 9 additions & 9 deletions sentry_sdk/traces.py
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@
self._sample_rate = sample_rate

self._start_timestamp = datetime.now(timezone.utc)
self._timestamp: "Optional[datetime]" = None
self._end_timestamp: "Optional[datetime]" = None

Check failure on line 294 in sentry_sdk/traces.py

View check run for this annotation

@sentry/warden / warden: code-review

Rename leaves stale `_timestamp` reference in `_span_batcher.py`, causing AttributeError when serializing spans

The PR renames `StreamedSpan._timestamp` to `_end_timestamp`, but `sentry_sdk/_span_batcher.py` still accesses `item._timestamp` at lines 171-172 in `_to_transport_format`. Since `StreamedSpan` no longer defines `_timestamp`, this attribute access will raise `AttributeError` at runtime whenever a streamed span is serialized for transport, breaking span streaming entirely and preventing `end_timestamp` from ever being sent to Sentry.
Comment thread
sentrivana marked this conversation as resolved.
Comment thread
sentry-warden[bot] marked this conversation as resolved.

# profiling depends on this value and requires that
# it is measured in nanoseconds
Expand Down Expand Up @@ -327,7 +327,7 @@
def __exit__(
self, ty: "Optional[Any]", value: "Optional[Any]", tb: "Optional[Any]"
) -> None:
if self._timestamp is not None:
if self._end_timestamp is not None:
# This span is already finished, ignore
return

Expand Down Expand Up @@ -361,7 +361,7 @@
self._previous_span_on_scope = old_span

def _end(self, end_timestamp: "Optional[Union[float, datetime]]" = None) -> None:
if self._timestamp is not None:
if self._end_timestamp is not None:
# This span is already finished, ignore.
return

Expand Down Expand Up @@ -392,15 +392,15 @@
pass

if isinstance(end_timestamp, datetime):
self._timestamp = end_timestamp
self._end_timestamp = end_timestamp
else:
logger.debug(
"[Tracing] Failed to set end_timestamp. Using current time instead."
)

if self._timestamp is None:
if self._end_timestamp is None:
elapsed = nanosecond_time() - self._start_timestamp_monotonic_ns
self._timestamp = self._start_timestamp + timedelta(
self._end_timestamp = self._start_timestamp + timedelta(

Check failure on line 403 in sentry_sdk/traces.py

View check run for this annotation

@sentry/warden / warden: find-bugs

_span_batcher._to_transport_format references removed attribute item._timestamp

After renaming `_timestamp` to `_end_timestamp` on `StreamedSpan`, `sentry_sdk/_span_batcher.py` lines 171-172 still access `item._timestamp`. Combined with `__slots__`, reading this attribute will raise `AttributeError`, so serializing any span for transport will fail and no spans will be sent. The serialized payload will also be missing `end_timestamp` even if the access were tolerated.
microseconds=elapsed / 1000
)

Expand Down Expand Up @@ -479,8 +479,8 @@
return self._start_timestamp

@property
def timestamp(self) -> "Optional[datetime]":
return self._timestamp
def end_timestamp(self) -> "Optional[datetime]":
return self._end_timestamp
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Renamed property breaks openai_agents integration at runtime

High Severity

The timestamp property on StreamedSpan was renamed to end_timestamp, but three call sites in the openai_agents integration still access span.timestamp on spans that can be StreamedSpan instances (when span streaming is enabled via get_start_span_function). This causes an AttributeError at runtime. The most critical site is in _run_single_turn (agent_run.py), where the AttributeError is not wrapped in capture_internal_exceptions(), so it replaces the original exception being handled.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit ea2436c. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

If this is true, how come our tests didn't catch this? 🙈

Copy link
Copy Markdown
Contributor Author

@sentrivana sentrivana May 7, 2026

Choose a reason for hiding this comment

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

Ah right, openai agents doesn't support span streaming yet, so that's ok.


def _is_segment(self) -> bool:
return self._segment is self
Expand Down Expand Up @@ -699,7 +699,7 @@
return None

@property
def timestamp(self) -> "Optional[datetime]":
def end_timestamp(self) -> "Optional[datetime]":
return None


Expand Down
4 changes: 2 additions & 2 deletions sentry_sdk/tracing_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ def add_query_source(
return

end_timestamp = (
datetime.now(timezone.utc) if span.timestamp is None else span.timestamp
datetime.now(timezone.utc) if span.end_timestamp is None else span.end_timestamp
)

duration = end_timestamp - span.start_timestamp
Expand Down Expand Up @@ -443,7 +443,7 @@ def add_http_request_source(
return

end_timestamp = (
datetime.now(timezone.utc) if span.timestamp is None else span.timestamp
datetime.now(timezone.utc) if span.end_timestamp is None else span.end_timestamp
)

duration = end_timestamp - span.start_timestamp
Expand Down
Loading