{"record":{"id":"9b1ab5a0b5ecfc7d","repo":"langchain-ai/deepagents","slug":"expires-at-is-only-meaningful-when-logged-in-i","errorCode":null,"errorMessage":"`expires_at` is only meaningful when `logged_in` is True.","messagePattern":"`expires_at` is only meaningful when `logged_in` is True\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/integrations/openai_codex.py","lineNumber":112,"sourceCode":"\n        Raises:\n            ValueError: An unreadable token is also marked `logged_in`; a\n                logged-out snapshot carries an `expires_at`, `is_expired`,\n                `account_id`, or `plan_type`; or a logged-in snapshot is\n                missing its `expires_at`.\n        \"\"\"\n        if self.unreadable_reason is not None and self.logged_in:\n            msg = (\n                \"`unreadable_reason` implies the token is not usable; \"\n                \"`logged_in` must be False.\"\n            )\n            raise ValueError(msg)\n        if self.logged_in and self.expires_at is None:\n            msg = \"`expires_at` must be set when `logged_in` is True.\"\n            raise ValueError(msg)\n        if not self.logged_in and self.expires_at is not None:\n            msg = \"`expires_at` is only meaningful when `logged_in` is True.\"\n            raise ValueError(msg)\n        if not self.logged_in and self.is_expired:\n            msg = \"`is_expired` is only meaningful when `logged_in` is True.\"\n            raise ValueError(msg)\n        if not self.logged_in and (self.account_id or self.plan_type):\n            msg = (\n                \"`account_id`/`plan_type` are only meaningful when `logged_in` is True.\"\n            )\n            raise ValueError(msg)\n\n\ndef default_store_path() -> Path:\n    \"\"\"Return the ChatGPT OAuth token store path.\n\n    Stored under Deep Agents' own state dir\n    (`~/.deepagents/.state/chatgpt-auth.json`) so the credential lives\n    alongside the rest of the app's state rather than in `langchain_openai`'s\n    default `~/.langchain`.\n    \"\"\"","sourceCodeStart":94,"sourceCodeEnd":130,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/integrations/openai_codex.py#L94-L130","documentation":"`__post_init__` invariant: `expires_at` is only meaningful for a logged-in token, so constructing the state with `logged_in=False` while `expires_at` is set raises ValueError. This keeps logged-out state objects from carrying stale expiry data that could mislead callers.","triggerScenarios":"`TokenState(logged_in=False, expires_at=<datetime>)` — e.g. representing a logged-out user by flipping the flag while leaving the old expiry in place.","commonSituations":"Logging out by only setting `logged_in=False` without clearing fields, restoring a cached snapshot after logout, or default-constructing with a leftover expiry value.","solutions":["Set `expires_at=None` when `logged_in=False`.","If the expiry is still relevant, keep `logged_in=True`.","On logout, construct a fresh state with all optional fields cleared."],"exampleFix":"// before\nstate = CodexAuthState(logged_in=False, expires_at=old_expiry)\n// after\nstate = CodexAuthState(logged_in=False, expires_at=None)","handlingStrategy":"validation","validationCode":"def valid_logged_out_state(state) -> bool:\n    return not (not state.logged_in and state.expires_at is not None)","typeGuard":null,"tryCatchPattern":"try:\n    state = CodexAuthState(logged_in=False, expires_at=old)\nexcept ValueError:\n    state = CodexAuthState(logged_in=False)","preventionTips":["On logout, build a fresh state instead of mutating logged_in only","Clear all optional fields (expires_at, account_id, plan_type) when logged_in=False","Keep a logout() helper as the only path to logged-out state"],"tags":["python","validation","dataclass","state"],"backgroundTag":"invariant-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}