-
Notifications
You must be signed in to change notification settings - Fork 565
Closed
Description
How do you use Sentry?
Sentry Saas (sentry.io)
Version
2.33.2
Steps to Reproduce
#!/usr/bin/env python3
"""
Minimal reproduction case for Sentry isolation_scope + async generator bug.
Bug: Using sentry_sdk.isolation_scope() as a context manager around an async
generator that yields causes "Token was created in a different Context" error
when the generator exits early (via break, exception, or garbage collection).
"""
import asyncio
import sentry_sdk
from sentry_sdk.integrations.asyncio import AsyncioIntegration
async def inner_generator():
"""Simple async generator that yields values"""
for i in range(3):
print(f" Inner generator yielding: {i}")
yield i
async def problematic_async_generator():
"""
This pattern causes the context error.
The isolation_scope wraps yield statements in an async generator.
"""
with sentry_sdk.isolation_scope() as scope:
scope.set_user({"id": "test-user-123"})
scope.set_tag("example", "value")
async for value in inner_generator():
# THIS YIELD INSIDE ISOLATION_SCOPE IS THE PROBLEM
yield value
async def main():
print("Reproducing Sentry isolation_scope + async generator bug\n")
print("=" * 60)
# Initialize Sentry
sentry_sdk.init(
dsn=None, # No DSN needed to reproduce
integrations=[AsyncioIntegration()],
debug=True,
)
print("Test 1: Normal completion (works fine)")
print("-" * 40)
async for val in problematic_async_generator():
print(f"Received: {val}")
print("✅ No error when generator completes normally\n")
print("Test 2: Early exit with break (causes error)")
print("-" * 40)
async for val in problematic_async_generator():
print(f"Received: {val}")
if val == 1:
print("Breaking early...")
break # This causes the context error
# Give time for error to appear in output
await asyncio.sleep(0.1)
print("\n❌ Error appears above: 'Token was created in a different Context'")
print("\n" + "=" * 60)
print("The error happens because:")
print("1. isolation_scope() saves the current context when entering")
print("2. The async generator suspends/resumes across context boundaries")
print("3. When exiting early, cleanup happens in a different context")
print("4. Python's contextvars raises ValueError")
if __name__ == "__main__":
asyncio.run(main())
Expected Result
Not to crash
Actual Result
Test 2: Early exit with break (causes error)
----------------------------------------
Inner generator yielding: 0
Received: 0
Inner generator yielding: 1
Received: 1
Breaking early...
Task exception was never retrieved
future: <Task finished name='coroutine without __name__ (Sentry-wrapped)' coro=<patch_asyncio.<locals>._sentry_task_factory.<locals>._task_with_sentry_span_creation() done, defined at /Users/ntindle/Library/Caches/pypoetry/virtualenvs/autogpt-platform-backend-90-hPFvq-py3.12/lib/python3.12/site-packages/sentry_sdk/integrations/asyncio.py:42> exception=ValueError("<Token var=<ContextVar name='current_scope' default=None at 0x1033a7790> at 0x109af7300> was created in a different Context")>
Traceback (most recent call last):
File "/Users/ntindle/Library/Caches/pypoetry/virtualenvs/autogpt-platform-backend-90-hPFvq-py3.12/lib/python3.12/site-packages/sentry_sdk/scope.py", line 1755, in isolation_scope
yield new_isolation_scope
File "/Users/ntindle/code/agpt/AutoGPT/main/autogpt_platform/backend/./sentry_bug_repro.py", line 33, in problematic_async_generator
yield value
GeneratorExit
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/Users/ntindle/Library/Caches/pypoetry/virtualenvs/autogpt-platform-backend-90-hPFvq-py3.12/lib/python3.12/site-packages/sentry_sdk/integrations/asyncio.py", line 55, in _task_with_sentry_span_creation
reraise(*_capture_exception())
File "/Users/ntindle/Library/Caches/pypoetry/virtualenvs/autogpt-platform-backend-90-hPFvq-py3.12/lib/python3.12/site-packages/sentry_sdk/utils.py", line 1751, in reraise
raise value
File "/Users/ntindle/Library/Caches/pypoetry/virtualenvs/autogpt-platform-backend-90-hPFvq-py3.12/lib/python3.12/site-packages/sentry_sdk/integrations/asyncio.py", line 53, in _task_with_sentry_span_creation
result = await coro
^^^^^^^^^^
File "/Users/ntindle/code/agpt/AutoGPT/main/autogpt_platform/backend/./sentry_bug_repro.py", line 27, in problematic_async_generator
with sentry_sdk.isolation_scope() as scope:
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/contextlib.py", line 158, in __exit__
self.gen.throw(value)
File "/Users/ntindle/Library/Caches/pypoetry/virtualenvs/autogpt-platform-backend-90-hPFvq-py3.12/lib/python3.12/site-packages/sentry_sdk/scope.py", line 1760, in isolation_scope
_current_scope.reset(current_token)
ValueError: <Token var=<ContextVar name='current_scope' default=None at 0x1033a7790> at 0x109af7300> was created in a different Context
❌ Error appears above: 'Token was created in a different Context'
Workaround
Save the scope user and tags, then manually catch the error in the generator using capture_exception, then set the tags using scope._tags = previous
smuuf
Metadata
Metadata
Assignees
Projects
Status
No status