You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Traceback (most recent call last):
File "/app/.venv/lib/python3.14/site-packages/sentry_sdk/_log_batcher.py", line 33, in _to_transport_format
k: serialize_attribute(v) for (k, v) in item["attributes"].items()
RuntimeError: _core::PyFeatureContext is unsendable, but is being dropped on another thread"
I hit this too and put a fix together. The batcher's _flush_loop calls _flush() unguarded, so any exception there (the RuntimeError in this report, but really anything) propagates out of the loop and ends the daemon flusher thread. After that _ensure_thread() still sees _flusher_pid == pid and returns True, so add() keeps appending with nothing draining the buffer. Once it reaches MAX_BEFORE_DROP every later item is dropped silently for the rest of the process lifetime.
Following the issue title, I wrapped the flush in each loop (Batcher._flush_loop plus both flush calls in SpanBatcher._flush_loop) in capture_internal_exceptions(), so a bad batch is logged rather than fatal and the loop keeps running. Added a regression test per loop that drives one iteration where _flush raises then asserts the loop returns instead of propagating. They fail on current master and pass with the guard. They carry the tests_internal_exceptions marker since they intentionally exercise the internal-exception path. Green locally: the logs, metrics and span-batcher suites (73 tests), ruff check and ruff format, mypy sentry_sdk with no new errors.
Thanks. Opened #7186. I rebased onto current master first since the span batcher's _flush_loop had moved (the global-limit checks were reverted in #7168), re-applied the guard around both flush calls there and re-verified green: the two regression tests, the logs/metrics/span-batcher suites, ruff and mypy.
Activity
linear-code commentedon Aug 7, 2026
PY-2726
zkasuran commentedon Aug 12, 2026
I hit this too and put a fix together. The batcher's
_flush_loopcalls_flush()unguarded, so any exception there (theRuntimeErrorin this report, but really anything) propagates out of the loop and ends the daemon flusher thread. After that_ensure_thread()still sees_flusher_pid == pidand returnsTrue, soadd()keeps appending with nothing draining the buffer. Once it reachesMAX_BEFORE_DROPevery later item is dropped silently for the rest of the process lifetime.Following the issue title, I wrapped the flush in each loop (
Batcher._flush_loopplus both flush calls inSpanBatcher._flush_loop) incapture_internal_exceptions(), so a bad batch is logged rather than fatal and the loop keeps running. Added a regression test per loop that drives one iteration where_flushraises then asserts the loop returns instead of propagating. They fail on currentmasterand pass with the guard. They carry thetests_internal_exceptionsmarker since they intentionally exercise the internal-exception path. Green locally: the logs, metrics and span-batcher suites (73 tests),ruff checkandruff format,mypy sentry_sdkwith no new errors.Branch: https://github.com/zkasuran/sentry-python/tree/fix/tolerate-exceptions-in-flush-loop
Happy to open a PR if this direction looks right.
alexander-alderman-webb commentedon Aug 13, 2026
Feel free to PR, that sounds directionally correct.
fix(batcher): Do not let a failed flush kill the flusher thread (gets…
zkasuran commentedon Aug 13, 2026
Thanks. Opened #7186. I rebased onto current master first since the span batcher's
_flush_loophad moved (the global-limit checks were reverted in #7168), re-applied the guard around both flush calls there and re-verified green: the two regression tests, the logs/metrics/span-batcher suites, ruff and mypy.fix(batcher): Do not let a failed flush kill the flusher thread