{"record":{"id":"ea4498c2f54c77b3","repo":"github/copilot-sdk","slug":"unknown-session-params-session-id","errorCode":null,"errorMessage":"unknown session {params.session_id}","messagePattern":"unknown session (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/copilot/client.py","lineNumber":795,"sourceCode":"        # so the public tagged dictionary is already in the expected wire shape.\n        return cast(GitHubTokenAcquireResult, result)\n\n\nclass _HooksAdapter:\n    \"\"\"Adapts session-scoped hook dispatch to the generated ``HooksHandler`` protocol.\n\n    ``hooks.invoke`` is a client-global RPC method whose payload carries a\n    ``sessionId``. This adapter routes each invocation to the matching session's\n    registered hook handlers.\n    \"\"\"\n\n    def __init__(self, get_session: Callable[[str], CopilotSession | None]) -> None:\n        self._get_session = get_session\n\n    async def invoke(self, params: _HookInvokeRequest) -> _HookInvokeResponse:\n        session = self._get_session(params.session_id)\n        if session is None:\n            raise ValueError(f\"unknown session {params.session_id}\")\n        output = await session._handle_hooks_invoke(params.hook_type.value, params.input)\n        return _HookInvokeResponse(output=output)\n\n\n@dataclass\nclass _CopilotClientOptions:\n    \"\"\"Internal configuration carrier used by :class:`CopilotClient`.\n\n    This is not part of the public API: ``CopilotClient`` accepts all of\n    these options as keyword arguments directly.\n    \"\"\"\n\n    connection: RuntimeConnection | None = None\n    working_directory: str | None = None\n    log_level: LogLevel = \"info\"\n    env: dict[str, str] | None = None\n    github_token: str | None = None\n    base_directory: str | None = None","sourceCodeStart":777,"sourceCodeEnd":813,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L777-L813","documentation":"The hook dispatcher's invoke looks up the session by params.session_id via the provided getter; if no session matches, it raises ValueError('unknown session ...'). Hooks are routed to a specific session, so an unknown ID means the hook request cannot be delivered and processing stops.","triggerScenarios":"A hook invoke request arrives with a session_id that was never created, or the session was already closed/removed from the client's session map before the hook fired.","commonSituations":"Client restart or session timeout between agent event and hook delivery; reusing a session ID string from a previous run; concurrent code closing a session while hooks are still in flight; copying a session_id with extra characters.","solutions":["Confirm the session_id exists (client.get_session / session map) before sending or processing hooks","Recreate the session if it was stopped, and re-send the request with the new session_id","Guard against closing sessions while hooks are pending; check session lifecycle ordering in your code","Log the valid session IDs at failure time to spot stale IDs"],"exampleFix":"// before\nsession = client.get_session(session_id)\nsession.stop()  # session removed while hooks may still arrive\n// after\nsession = client.get_session(session_id)\n# drain/ignore pending hooks first, then stop\nif not has_pending_hooks(session_id):\n    session.stop()","handlingStrategy":"try-catch","validationCode":"if client.get_session(params.session_id) is None:\n    raise LookupError(f\"session {params.session_id} not found; skip hook\")","typeGuard":null,"tryCatchPattern":"try:\n    output = await hook_handler.invoke(params)\nexcept ValueError as e:\n    if str(e).startswith(\"unknown session\"):\n        logger.warning(\"dropping hook for stale session %s\", params.session_id)\n    else:\n        raise","preventionTips":["Track session lifecycles and drop pending hooks on session close","Never cache session IDs across client restarts","Validate session_id against the live session map before dispatching hooks"],"tags":["python","session-lifecycle","hooks"],"backgroundTag":"record-not-found","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}