{"record":{"id":"bf9499ad08b6d4be","repo":"SeleniumHQ/selenium","slug":"fn-name-must-be-called-in-a-session-context","errorCode":null,"errorMessage":"{fn_name}() must be called in a session context.","messagePattern":"(.+?)\\(\\) must be called in a session context\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"py/private/cdp.py","lineNumber":105,"sourceCode":"    If there is no current connection, raise a ``RuntimeError`` with a\n    helpful message.\n    \"\"\"\n    try:\n        return _connection_context.get()\n    except LookupError:\n        raise RuntimeError(f\"{fn_name}() must be called in a connection context.\")\n\n\ndef get_session_context(fn_name):\n    \"\"\"Look up the current session.\n\n    If there is no current session, raise a ``RuntimeError`` with a\n    helpful message.\n    \"\"\"\n    try:\n        return _session_context.get()\n    except LookupError:\n        raise RuntimeError(f\"{fn_name}() must be called in a session context.\")\n\n\n@contextmanager\ndef connection_context(connection):\n    \"\"\"Context manager installs ``connection`` as the session context for the current Trio task.\"\"\"\n    token = _connection_context.set(connection)\n    try:\n        yield\n    finally:\n        _connection_context.reset(token)\n\n\n@contextmanager\ndef session_context(session):\n    \"\"\"Context manager installs ``session`` as the session context for the current Trio task.\"\"\"\n    token = _session_context.set(session)\n    try:\n        yield","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/private/cdp.py#L87-L123","documentation":"Raised as a RuntimeError by get_session_context(fn_name) when the contextvars.ContextVar _session_context has no value set (LookupError). The CDP module uses session_context to implicitly route CDP commands to a specific target/session; CDP session-scoped functions call get_session_context to retrieve it. If called outside a session_context() block or an `async with connection.session(target):` context, no session is available.","triggerScenarios":"Calling a CDP session-scoped function (e.g. dom.get_document() inside a session, runtime.evaluate on a specific target) outside of `with session_context(session):` or `async with conn.session(target_id):`. The ContextVar lookup raises LookupError which is re-raised as RuntimeError.","commonSituations":"Calling session-scoped CDP methods before entering the session context; code moved out of the `async with session:` block during refactoring; using CDP in a spawned Trio task that does not copy the contextvar; targeting multiple sessions and forgetting to switch context.","solutions":["Ensure session-scoped CDP calls are inside `async with conn.session(target_id) as session:` or `with session_context(session):`.","For background tasks or callbacks, explicitly set the session context within that task's scope.","If you only need connection-level (not session-level) CDP calls, use the connection context instead (error 112)."],"exampleFix":"# before\nasync def main():\n    conn = await Connection.create(url)\n    session = await conn.connect_session(target_id)\n    result = await runtime.evaluate('1+1')  # RuntimeError: no session\n\n# after\nasync def main():\n    conn = await Connection.create(url)\n    async with conn.session(target_id) as session:\n        result = await runtime.evaluate('1+1')  # session context set","handlingStrategy":"try-catch","validationCode":"from selenium.webdriver.common.bidi.cdp import get_session_context\ntry:\n    sess = get_session_context('check')\nexcept RuntimeError:\n    # enter a session context first\n    pass","typeGuard":null,"tryCatchPattern":"try:\n    await runtime.evaluate('1+1')\nexcept RuntimeError as e:\n    if 'session context' in str(e):\n        async with conn.session(target_id):\n            await runtime.evaluate('1+1')\n    else:\n        raise","preventionTips":["Wrap session-scoped CDP calls in `async with conn.session(target_id):`.","Keep session-scoped code inside the context block — do not move it out during refactoring.","Re-establish session context in spawned tasks."],"tags":["python","cdp","contextvars","session","trio"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}