{"record":{"id":"8c4f8421c97e3bd6","repo":"langchain-ai/deepagents","slug":"unreadable-reason-implies-the-token-is-not-usabl","errorCode":null,"errorMessage":"`unreadable_reason` implies the token is not usable; `logged_in` must be False.","messagePattern":"`unreadable_reason` implies the token is not usable; `logged_in` must be False\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"libs/code/deepagents_code/integrations/openai_codex.py","lineNumber":106,"sourceCode":"\n        The valid/expired/missing/unreadable states are encoded as a\n        `bool` plus optionals rather than a tagged union, so this guards the\n        cross-field rules the attribute docs promise — catching future\n        construction drift the same way upstream's `_ChatGPTToken` guards\n        its own invariants.\n\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.","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/langchain-ai/deepagents/blob/a1af029e6e73cb17c36bff823d227747b28e91e1/libs/code/deepagents_code/integrations/openai_codex.py#L88-L124","documentation":"This ValueError is raised by a dataclass `__post_init__` invariant check on a Codex auth token state object. The library enforces that `unreadable_reason` (indicating the stored token could not be read/decoded) can only coexist with `logged_in=False`, since an unreadable token means the user cannot be considered logged in. It protects callers from a contradictory state object.","triggerScenarios":"Constructing the dataclass with both `unreadable_reason` set to a non-None value AND `logged_in=True`, e.g. `TokenState(unreadable_reason='corrupt file', logged_in=True)`.","commonSituations":"Hand-building a token state from partially recovered auth files, deserializing a snapshot where a login was attempted but token parsing failed, or code that sets `unreadable_reason` after marking the session logged in.","solutions":["Set `logged_in=False` whenever `unreadable_reason` is populated.","If the user actually authenticated, clear `unreadable_reason` (set to None) and supply `expires_at` instead.","Re-read the auth file and recover the token so neither invariant is violated."],"exampleFix":"// before\nstate = CodexAuthState(unreadable_reason='token file corrupt', logged_in=True)\n// after\nstate = CodexAuthState(unreadable_reason='token file corrupt', logged_in=False)","handlingStrategy":"validation","validationCode":"def validate_auth_state(state) -> bool:\n    return not (state.unreadable_reason is not None and state.logged_in)","typeGuard":null,"tryCatchPattern":"try:\n    state = CodexAuthState(unreadable_reason=reason, logged_in=True)\nexcept ValueError as exc:\n    logger.warning('invalid auth state: %s', exc)\n    state = CodexAuthState(unreadable_reason=reason, logged_in=False)","preventionTips":["Always set logged_in=False when unreadable_reason is populated","Construct auth state through a single factory that enforces invariants","Add a unit test for each invariant branch"],"tags":["python","validation","dataclass","invariant"],"backgroundTag":"invariant-validation-failed","analyzedSha":"a1af029e6e73cb17c36bff823d227747b28e91e1","analyzedAt":"2026-08-29T11:43:24.718Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}