{"record":{"id":"4e7c8a5d859eb279","repo":"D4Vinci/Scrapling","slug":"session-session-id-already-registered","errorCode":null,"errorMessage":"Session '{session_id}' already registered","messagePattern":"Session '(.+?)' already registered","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scrapling/spiders/session.py","lineNumber":31,"sourceCode":"    \"\"\"Manages pre-configured session instances.\"\"\"\n\n    def __init__(self) -> None:\n        self._sessions: dict[str, Session] = {}\n        self._default_session_id: str | None = None\n        self._started: bool = False\n        self._lazy_sessions: Set[str] = set()\n        self._lazy_lock = Lock()\n\n    def add(self, session_id: str, session: Session, *, default: bool = False, lazy: bool = False) -> \"SessionManager\":\n        \"\"\"Register a session instance.\n\n        :param session_id: Name to reference this session in requests\n        :param session: Your pre-configured session instance\n        :param default: If True, this becomes the default session\n        :param lazy: If True, the session will be started only when a request uses its ID.\n        \"\"\"\n        if session_id in self._sessions:\n            raise ValueError(f\"Session '{session_id}' already registered\")\n\n        self._sessions[session_id] = session\n\n        if default or self._default_session_id is None:\n            self._default_session_id = session_id\n\n        if lazy:\n            self._lazy_sessions.add(session_id)\n\n        return self\n\n    def remove(self, session_id: str) -> None:\n        \"\"\"Removes a session.\n\n        :param session_id: ID of session to remove\n        \"\"\"\n        _ = self.pop(session_id)\n","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/D4Vinci/Scrapling/blob/5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f/scrapling/spiders/session.py#L13-L49","documentation":"SessionManager.add() refuses to register two sessions under the same session_id, raising ValueError to prevent silently replacing an existing session's configuration. Session IDs are the lookup keys used by requests, so duplicates would create ambiguous routing.","triggerScenarios":"Calling spider/session_manager.add('http', session) twice, or adding sessions with the same name from two different modules/plugins during spider setup.","commonSituations":"Registering sessions in a loop over a config list that contains a repeated name; a base spider subclass and a plugin both registering a session called 'default'.","solutions":["Give each session a unique id: add('browser', camoufox_session) vs add('api', httpx_session).","Use pop(session_id) first if intentional replacement is desired, then add() again.","Check registration state before adding: if session_id not in manager.session_ids.","Audit config files for duplicate session names."],"exampleFix":"# before\nmanager.add('fetch', session_a)\nmanager.add('fetch', session_b)  # ValueError\n\n# after\nmanager.add('fetch', session_a)\nmanager.add('fetch-2', session_b)","handlingStrategy":"validation","validationCode":"if session_id in manager.session_ids:\n    manager.pop(session_id)  # explicit replace policy\nmanager.add(session_id, session, default=is_default)","typeGuard":null,"tryCatchPattern":"try:\n    manager.add(session_id, session)\nexcept ValueError as e:\n    if 'already registered' in str(e):\n        logger.warning('session %r re-registered; replacing', session_id)\n        manager.pop(session_id)\n        manager.add(session_id, session)\n    else:\n        raise","preventionTips":["Define session ids as module-level constants used by both setup and request code.","Deduplicate session names when loading from config files."],"tags":["session","registration","value-error","configuration"],"backgroundTag":null,"analyzedSha":"5d213a2d4764002bfc4fed33c32fe09fa8b0bf7f","analyzedAt":"2026-08-14T22:23:09.440Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}