Repository navigation
[Bug]: ChatGPT connections end after an hour because every refresh returns invalid_grant #14356
Description
Activity
Triage
Thanks for the write-up. The refresh request you quoted matches what T3 sends, and it also matches OpenAI's Refreshing tokens section: a form-encoded
grant_type=refresh_token, the issuedoaiapp_client id (notdynamic_agent_client), the saved refresh token, andresource=https://api.openai.com/v1, withscopeleft out, posted to the discovered token endpoint.Clearing the session on
invalid_grantis the recovery OpenAI documents for an unusable refresh token (Refresh errors): drop the dead token set and run OAuth again with the saved client id. T3 does that and keeps the registration, so reconnecting doesn't create a new client. A transient failure such as503doesn't clear the credentials, and the refresh-recovery tests inCodexChatGptAuth.test.tscover that path.Two corrections to the T3-specific claims:
- This was reproduced with graff and curl, not with T3. The claim that every T3 connection dies after an hour is inferred from the request shape.
- "Your ChatGPT connection expired or was disconnected. Sign in again." isn't what this path shows.
exchangebuilds that error, butaccessthen remaps every refresh failure exceptinvalid_clientto "Could not renew the ChatGPT connection. Retry, or sign in again." The credentials are still removed before that remap.
ext_agent_host_idis required on the authorize request but isn't part of the documented refresh body, so leaving it off isn't a T3 bug. Attempts 5–7 also reused a token OpenAI had already refused, so they don't show whether a first refresh with extra fields would succeed.There are no other reports of this from a T3 session. Managed ChatGPT auth landed in merged PR #14290 about ten hours before this issue was filed. If OpenAI is rejecting a spec-matching refresh from every client, the fix is on their side. T3 shouldn't keep retrying
invalid_grantor keep a rejected refresh token around.To treat this as a T3 bug, we need a capture from an actual T3 session, not another client. Sign in with ChatGPT in T3 and leave that session alone until after
earliest_refresh_atand within a minute of the access token expiring. Then capture the token endpoint's status,errorcode, andx-request-id, with the refresh token and client id redacted. A graffx-request-idis useful to OpenAI, but it doesn't show that T3 hit the same refusal.- addedneeds more infoInitial triage showed no bug. Awaiting more infoInitial triage showed no bug. Awaiting more infovia-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 30, 2026 Disclosure: written by an AI coding assistant for the reporter, and reviewed before posting.
Update: this reproduces with OpenAI's own reference implementation, so it isn't specific to T3 Code or to how any client builds the request.
Using openai/sign-in-with-chatgpt-devkit
packages/local, unmodified:- A new registration, without
ext_agent_host_id(the devkit's default). - The devkit's own refresh, sent in its own window: past
earliest_refresh_at, 39 s before expiry, on a never-used refresh token. - The result was
400 invalid_grant("ChatGPT did not accept this authorization grant").
A second client renewed its own fresh sign-in a few minutes later, inside its window, and got the same answer: "The refresh token has been invalidated. A fresh sign-in is required."
That matches the triage above: the request is the documented one, so the fix has to come from OpenAI. Reported upstream with the full reproduction, code links for the devkit, T3 Code, pi and Codegraff, and what was ruled out: openai/sign-in-with-chatgpt-devkit#5
- A new registration, without
I'm also experiencing a similar one-hour expiry symptom in T3 Code itself on macOS, using managed ChatGPT sign-in with T3 Code Nightly 0.0.46-nightly.20261004.2644.
The ChatGPT connection stops working after about one hour. I'm currently seeing a 429 error. Restarting T3 Code temporarily fixes it and restores access, so I have to restart T3 Code roughly every hour to keep working.
For clarity, earlier diagnostic checks also confirmed 401
token_expirederrors from the running managed Codex process. The current 429 is my reported symptom, not a separately verified diagnostic result. Since restarting restores access, I haven't confirmed that this is the sameinvalid_grantfailure described in the original report.@stantaneous This happens if your account had a change in security settings, this includes if you recently did a password reset, or enrolled in AAS / Daybreak Blue.
Before submitting
Area
apps/server
Steps to reproduce
CodexChatGptAuthrenews it within 60 seconds of expiry, onceearliest_refresh_athas passed (CodexChatGptAuth.ts L729-L748).Without T3 Code: take a token set from any client of this flow and, inside the renewal window, send the same request:
Expected behavior
HTTP 200 with a new access token and a replacement refresh token, so the connection stays up.
Actual behavior
OpenAI answers
400 {"error": "invalid_grant"}with noerror_description. T3 Code treatsinvalid_granton a refresh as a dead token (L391-L406): it removes the connection and shows "Your ChatGPT connection expired or was disconnected. Sign in again." So every connection should end about an hour after sign-in.We sent this request eight times across three sign-ins: before and after
earliest_refresh_at, 60 seconds before expiry (T3 Code's timing), after expiry, and withext_agent_host_idorscopeadded orresourcedropped (those three reused a token that had just been refused). Every one was refused, including never-used tokens inside the renewal window. pi and nolune send the same four fields.Impact
Major degradation or frequent failure
Version or commit
main @ 0fcd5f9
Environment
Not environment-specific: the refusal comes from OpenAI's token endpoint. Reproduced with curl and Python on macOS.
Logs or stack traces
HTTP/1.1 400 Bad Request {"error": "invalid_grant"}Workaround
Sign in again when the connection ends. T3 Code's request matches the documented one, so there may be nothing to change here unless OpenAI says a refresh needs more.
Full report, with every attempt, a reproduction script, and the refresh code of T3 Code, pi and nolune: https://github.com/justrach/codegraff/blob/feat/chat-gpt-new/docs/upstream/openai-sign-in-refresh-invalid-grant.md
Tracked for graff in justrach/codegraff#1422.