langchain-ai/deepagents · error · ValueError

`expires_at` is only meaningful when `logged_in` is True.

Error message

`expires_at` is only meaningful when `logged_in` is True.

What it means

`__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.

Source

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

        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.

    Stored under Deep Agents' own state dir
    (`~/.deepagents/.state/chatgpt-auth.json`) so the credential lives
    alongside the rest of the app's state rather than in `langchain_openai`'s
    default `~/.langchain`.
    """

View on GitHub (pinned to a1af029e6e)

Solutions

  1. Set `expires_at=None` when `logged_in=False`.
  2. If the expiry is still relevant, keep `logged_in=True`.
  3. On logout, construct a fresh state with all optional fields cleared.

Example fix

// before
state = CodexAuthState(logged_in=False, expires_at=old_expiry)
// after
state = CodexAuthState(logged_in=False, expires_at=None)
Defensive patterns

Strategy: validation

Validate before calling

def valid_logged_out_state(state) -> bool:
    return not (not state.logged_in and state.expires_at is not None)

Try / catch

try:
    state = CodexAuthState(logged_in=False, expires_at=old)
except ValueError:
    state = CodexAuthState(logged_in=False)

Prevention

When it happens

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

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

Related errors


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