langchain-ai/deepagents · error · ValueError

`unreadable_reason` implies the token is not usable; `logged

Error message

`unreadable_reason` implies the token is not usable; `logged_in` must be False.

What it means

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.

Source

Thrown at libs/code/deepagents_code/integrations/openai_codex.py:106

        The valid/expired/missing/unreadable states are encoded as a
        `bool` plus optionals rather than a tagged union, so this guards the
        cross-field rules the attribute docs promise — catching future
        construction drift the same way upstream's `_ChatGPTToken` guards
        its own invariants.

        Raises:
            ValueError: An unreadable token is also marked `logged_in`; a
                logged-out snapshot carries an `expires_at`, `is_expired`,
                `account_id`, or `plan_type`; or a logged-in snapshot is
                missing its `expires_at`.
        """
        if self.unreadable_reason is not None and self.logged_in:
            msg = (
                "`unreadable_reason` implies the token is not usable; "
                "`logged_in` must be False."
            )
            raise ValueError(msg)
        if self.logged_in and self.expires_at is None:
            msg = "`expires_at` must be set when `logged_in` is True."
            raise ValueError(msg)
        if not self.logged_in and self.expires_at is not None:
            msg = "`expires_at` is only meaningful when `logged_in` is True."
            raise ValueError(msg)
        if not self.logged_in and self.is_expired:
            msg = "`is_expired` is only meaningful when `logged_in` is True."
            raise ValueError(msg)
        if not self.logged_in and (self.account_id or self.plan_type):
            msg = (
                "`account_id`/`plan_type` are only meaningful when `logged_in` is True."
            )
            raise ValueError(msg)


def default_store_path() -> Path:
    """Return the ChatGPT OAuth token store path.

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Set `logged_in=False` whenever `unreadable_reason` is populated.
  2. If the user actually authenticated, clear `unreadable_reason` (set to None) and supply `expires_at` instead.
  3. Re-read the auth file and recover the token so neither invariant is violated.

Example fix

// before
state = CodexAuthState(unreadable_reason='token file corrupt', logged_in=True)
// after
state = CodexAuthState(unreadable_reason='token file corrupt', logged_in=False)
Defensive patterns

Strategy: validation

Validate before calling

def validate_auth_state(state) -> bool:
    return not (state.unreadable_reason is not None and state.logged_in)

Try / catch

try:
    state = CodexAuthState(unreadable_reason=reason, logged_in=True)
except ValueError as exc:
    logger.warning('invalid auth state: %s', exc)
    state = CodexAuthState(unreadable_reason=reason, logged_in=False)

Prevention

When it happens

Trigger: 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)`.

Common situations: 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.

Related errors


AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29). Data as JSON: /api/errors/8c4f8421c97e3bd6. Report an issue: GitHub.