From b41634d892c1f33a0660b7387cbc8b61ab11cde2 Mon Sep 17 00:00:00 2001 From: JesseMarkowitz Date: Fri, 27 Feb 2026 23:34:54 -0500 Subject: [PATCH] fix: load .env in doctor command; handle JWE tokens gracefully MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doctor was reading env vars before loading .env, so tokens set in .env were invisible. ChatGPT now uses JWE (encrypted JWT) tokens which PyJWT cannot decode without the server key — treat decode failure as "token set, expiry unknown" rather than a FAIL. Co-Authored-By: Claude Sonnet 4.6 --- src/config.py | 8 ++++++-- src/main.py | 10 ++++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/config.py b/src/config.py index 7ebf41b..7085523 100644 --- a/src/config.py +++ b/src/config.py @@ -125,8 +125,12 @@ def _validate_chatgpt_token(token: str) -> datetime | None: try: payload = jwt.decode(token, options={"verify_signature": False}) - except jwt.DecodeError as e: - logger.warning("CHATGPT_SESSION_TOKEN could not be decoded as JWT: %s", e) + except jwt.DecodeError: + # JWE (encrypted JWT, alg=dir) — cannot be decoded without the server key. + # This is normal for ChatGPT's current token format. Token is valid; expiry unknown. + logger.debug( + "CHATGPT_SESSION_TOKEN is an encrypted JWE token — expiry cannot be decoded client-side." + ) return None exp = payload.get("exp") diff --git a/src/main.py b/src/main.py index 9bce353..7366a50 100644 --- a/src/main.py +++ b/src/main.py @@ -256,6 +256,10 @@ def _run_doctor_checks() -> list[dict]: import os import jwt as pyjwt from datetime import timezone + from dotenv import load_dotenv + + # Load .env so doctor works without the user having to export vars manually + load_dotenv(override=False) checks = [] @@ -288,8 +292,10 @@ def _run_doctor_checks() -> list[dict]: add("ChatGPT token expiry warning", False, "Expires in < 24h — refresh soon") else: add("ChatGPT token expiry", False, "JWT has no 'exp' claim") - except Exception as e: - add("ChatGPT token decode", False, str(e)) + except pyjwt.exceptions.DecodeError: + # JWE (encrypted JWT) — cannot decode without the server key. + # This is normal for ChatGPT's current token format. Token is present and valid. + add("ChatGPT token expiry", True, "Encrypted token (JWE) — expiry not decodable client-side") # Claude key if claude_key: