Skip to content

Renew a ChatGPT subscription login that ChatGPT rejects during a run - #351

Open
arseniycodes wants to merge 1 commit into
mainfrom
ash/renew-rejected-chatgpt-login
Open

arseniycodes wants to merge 1 commit into
mainfrom
ash/renew-rejected-chatgpt-login

Conversation

@arseniycodes

@arseniycodes arseniycodes commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Problem

A customer's ChatGPT-subscription automation failed every run for about 20 hours with:

Codex automation harness failed: workspace routing discovery unauthorized (401)

Before a turn, Codex calls chatgpt.com/backend-api/accounts/check. ChatGPT returned 401 for the stored access token, even though the token had not reached its exp. Codex would normally refresh after a 401, but a run sandbox holds only the run-only refresh token. The worker renews the stored login only when the token is close to expiry (subscriptionAuthCoveringRun), so nothing renewed it. Runs recovered only after someone opened the model picker, which runs Codex with the real refresh token and saved a new login.

Change

  • runCodexAutomation throws SubscriptionLoginRejectedError (a subclass of AutomationHarnessError) when a subscription run ends with a ChatGPT 401 (unauthorized (401) or 401 Unauthorized in the final Codex error).
  • On that error, processAutomationRun calls the new refreshSubscription dependency (refreshSubscriptionInSandbox). account/read with refreshToken: true refreshes even when the token has not expired, so the next run gets a new token.
  • The failing run still fails with the same message. Refresh failures are reported to Sentry, except SubscriptionCredentialUnavailableError, which means another operation is already renewing the login.

Re-running the failed turn is out of scope. It would need a new Daytona secret and sandbox and would affect notification handling.

Verification

  • New tests: the harness classifies the 401; the run renews the login on that error and does not renew it on other harness failures.
  • pnpm typecheck, eslint on the changed files, and vitest run apps/worker (673 passed) pass.

Summary by cubic

Renews a stored ChatGPT subscription login as soon as a run reports a ChatGPT 401, instead of waiting until the token nears expiry.

  • A subscription run that ends with unauthorized (401) or 401 Unauthorized now throws a SubscriptionLoginRejectedError, and the worker immediately refreshes the stored login so the next run uses a fresh token.
  • The failing run still fails with the same message. Refresh failures are reported to Sentry, except SubscriptionCredentialUnavailableError, which means another run is already renewing the login.

Written for commit 2b9227c. Summary will update on new commits.

View guided diff Turn on auto-fix

ChatGPT can reject a stored access token before its stated expiry. A run
holds no refresh token, and the worker renews the login only near expiry,
so every run failed with a 401 until something else refreshed the login.

When a subscription run fails with a ChatGPT 401, the worker now renews
the stored login right away, so the next run uses a fresh token.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant