Skip to content

_is_contextvars_broken: eventlet import raises AttributeError instead of ImportError, crashing SDK init #7202

Description

@HumanistAtypik

Summary

_is_contextvars_broken() in sentry_sdk/utils.py wraps the eventlet.patcher import in except ImportError:, but importing eventlet can raise AttributeError (not ImportError) when trio is also installed. This crashes SDK initialization at import time.

Environment

  • sentry-sdk: 2.66.1
  • Python: 3.14
  • eventlet: 0.41.0
  • greenlet: 3.5.1
  • trio: 0.33.0
  • httpcore: 1.0.9
  • dnspython: 2.8.0
  • OS: Arch Linux (rolling)

Reproduction

# With eventlet, trio, httpcore, and dnspython all installed:
import sentry_sdk
# → AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'

Minimal repro (no app code needed)

python3 -c "import sentry_sdk"

Traceback

File "/usr/lib/python3.14/site-packages/sentry_sdk/__init__.py", line 1, in <module>
    from sentry_sdk import metrics, profiler
File "/usr/lib/python3.14/site-packages/sentry_sdk/metrics.py", line 5, in <module>
    from sentry_sdk.utils import format_attribute
File "/usr/lib/python3.14/site-packages/sentry_sdk/utils.py", line 1436, in <module>
    HAS_REAL_CONTEXTVARS, ContextVar = _get_contextvars()
File "/usr/lib/python3.14/site-packages/sentry_sdk/utils.py", line 1406, in _get_contextvars
    if not _is_contextvars_broken():
File "/usr/lib/python3.14/site-packages/sentry_sdk/utils.py", line 1353, in _is_contextvars_broken
    from eventlet.patcher import is_monkey_patched  # type: ignore
File "/usr/lib/python3.14/site-packages/eventlet/__init__.py", line 6, in <module>
    from eventlet import convenience
File "/usr/lib/python3.14/site-packages/eventlet/convenience.py", line 7, in <module>
    from eventlet.green import socket
File "/usr/lib/python3.14/site-packages/eventlet/green/socket.py", line 21, in <module>
    from eventlet.support import greendns
File "/usr/lib/python3.14/site-packages/eventlet/support/greendns.py", line 78, in <module>
    setattr(dns, pkg, import_patched('dns.' + pkg))
File "/usr/lib/python3.14/site-packages/eventlet/support/greendns.py", line 60, in import_patched
    return patcher.import_patched(module_name, **modules)
File "/usr/lib/python3.14/site-packages/eventlet/patcher.py", line 138, in import_patched
    return inject(module_name, None, *additional_modules + tuple(kw_additional_modules.items()))
File "/usr/lib/python3.14/site-packages/eventlet/patcher.py", line 115, in inject
    module = __import__(module_name, {}, {}, module_name.split(".")[:-1])
File "/usr/lib/python3.14/site-packages/dns/asyncquery.py", line 40, in <module>
    from dns.query import (...)
File "/usr/lib/python3.14/site-packages/dns/query.py", line 70, in <module>
    import httpcore._backends.sync
File "/usr/lib/python3.14/site-packages/httpcore/__init__.py", line 1, in <module>
    from ._api import request, stream
File "/usr/lib/python3.14/site-packages/httpcore/_api.py", line 7, in <module>
    from ._sync.connection_pool import ConnectionPool
File "/usr/lib/python3.14/site-packages/httpcore/_sync/__init__.py", line 1, in <module>
    from .connection import HTTPConnection
File "/usr/lib/python3.14/site-packages/httpcore/_sync/connection.py", line 14, in <module>
    from .._synchronization import Lock
File "/usr/lib/python3.14/site-packages/httpcore/_synchronization.py", line 12, in <module>
    import trio
File "/usr/lib/python3.14/site-packages/trio/__init__.py", line 25, in <module>
    from . import abc, from_thread, lowlevel, socket, to_thread
File "/usr/lib/python3.14/site-packages/trio/socket.py", line 16, in <module>
    from . import _socket
File "/usr/lib/python3.14/site-packages/trio/_socket.py", line 759, in SocketType
    @_wraps(_stdlib_socket.socket.sendmsg, assigned=(), updated=())
AttributeError: type object 'GreenSocket' has no attribute 'sendmsg'

Root cause

The import chain is:

eventlet.patcher
  → eventlet.green.socket
    → eventlet.support.greendns
      → dns.asyncquery → dns.query
        → httpcore._backends.sync → httpcore
          → trio → trio._socket
            → @_wraps(_stdlib_socket.socket.sendmsg, ...)
              → AttributeError (GreenSocket lacks sendmsg)

When eventlet is imported (even just to check is_monkey_patched), it patches socket.socket to GreenSocket as a side effect of its own import chain. GreenSocket does not implement sendmsg. When trio is also installed, trio's _socket.py tries to @_wraps(_stdlib_socket.socket.sendmsg) at class-definition time, which raises AttributeError because socket.socket has already been replaced by GreenSocket.

The except ImportError: on line 1365 does not catch AttributeError, so the error propagates and crashes SDK initialization.

This was originally reported to trio as python-trio/trio#3015, closed as not planned — the position is that eventlet and trio should not be mixed. However, the Sentry SDK triggers this by importing eventlet unconditionally during _is_contextvars_broken(), even when eventlet is not actually in use by the application.

Suggested fix

Broaden the exception handler to catch any exception during the optional eventlet import, not just ImportError:

# sentry_sdk/utils.py, _is_contextvars_broken(), around line 1365

    try:
        import greenlet
        from eventlet.patcher import is_monkey_patched  # type: ignore
        ...
    except Exception:  # was: except ImportError
        pass

The same applies to the gevent block above it (line 1348), which also uses except ImportError: — gevent could similarly raise a non-ImportError during import in edge cases.

The intent of both blocks is clearly "if this optional dependency is unavailable or breaks on import, fall through." Catching Exception matches that intent.

Workaround

Locally patching except ImportError:except Exception: on both blocks resolves the crash. Confirmed working with sentry-sdk 2.66.1.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status
    Waiting for: Product Owner

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions