You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature]: Allow re-authentication / replacement of an expired pool account instead of blocking with "Account is already in the pool" #4066
Re-authenticate a Codex pool account that has expired or dropped its session (e.g., token revoked, session expired), so that the account becomes usable again without having to delete it from the pool first.
What prevents this today?
When a pool account expires and the operator tries to log in again via the WebUI (or CLI) using the same account credentials, checkAccountIdCollision (src/codex/auth-collision.ts) sees that the chatgptAccountId already exists in the pool config and rejects the login attempt with:
Account is already in the pool (chatgpt-...)
The only workaround today is a destructive 2-step process:
Delete the expired account from the pool.
Re-add it via a fresh login.
This destroys the account's usage history, quota recovery state, manually configured priority/strategy settings, and pool labels.
What should OpenCodex do?
When a login flow completes and checkAccountIdCollision detects that the account already exists in the pool, it should check if the existing pool account's session is expired, invalid, or being explicitly re-authenticated. Instead of aborting the flow with a collision error, OpenCodex should update the existing account in-place with the new credential/tokens, preserving its id, usage history, and configuration.
If an operator explicitly clicks "Re-authenticate" (or runs an equivalent CLI command), the collision check should be bypassed entirely for that specific account ID, or the merge logic should just overwrite the token material.
Example usage or interface
Dashboard shows a pool account as Expired / Needs re-authentication.
Operator clicks "Re-authenticate" on that account card.
OAuth/Device flow completes.
Instead of Account is already in the pool error, the UI says Account re-authenticated successfully and the token is updated. History and routing settings remain intact.
Alternatives or workarounds
Deleting the account and re-adding it — loses all historical usage data, manual aliases, and pool configuration.
Manually editing auth.json / config.json on the filesystem — error-prone and defeats the purpose of the management API.
이 이슈는 Codex 풀 계정이 만료·세션 끊김으로 못 쓰일 때, 같은 ChatGPT 계정으로 다시 로그인하면 checkAccountIdCollision이 “Account is already in the pool”로 막고, 그래서 풀에서 지운 뒤 다시 넣어야 해서 사용 기록·우선순위·라벨이 사라진다는 요청입니다. 작성자 nordz0r, 라벨은 enhancement + account-pool입니다. 관련로 본문이 적은 #3375(풀 라이프사이클)·#3846(등록이 warmup 성공에 묶임)은 아직 열려 있고, 비슷한 축의 #3898은 네이티브 main(__main__)을 headless 허브 WebUI에서 reauth하는 별 문제라 이 이슈와 같지 않습니다. 지금 로컬 dev HEAD는 8026405d9(#4067 wp7 프록시 stop 거절 사유), package 2.49.0입니다. types.ts/config.ts 분할·preview 배포와는 무관합니다. 이 번호로 열린 구현 PR은 없습니다.
왜 우선순위가 낮은가. 요청한 “제자리 재인증”은 이미 현재 dev에 들어가 있습니다. 새 계정 추가 경로만 보면 본문 설명이 맞습니다. src/codex/auth-collision.ts의 checkAccountIdCollision은 같은 개인/워크스페이스 버킷 안에서 같은 chatgptAccountId(그리고 이메일이 있으면 같은 이메일)를 보면 충돌로 끝냅니다. 그런데 네 번째 인자 excludeAccountId가 있고, 재인증일 때는 그 슬롯을 건너뜁니다. src/codex/auth-api.ts의 POST /api/codex-auth/login은 body에 reauth: true와 풀 id가 오면 재인증 모드로 갑니다. 같은 ChatGPT 정체인지 확인한 뒤, 충돌 검사에서 그 id를 빼고, 자격 증명을 그 풀 id 위에 덮어씁니다. 성공하면 clearAccountNeedsReauth로 격리도 풉니다. 풀 행 id는 그대로라서, 본문이 걱정한 “지우고 다시 넣기”로 히스토리가 날아가는 경로를 피할 수 있게 이미 설계되어 있습니다.
화면과 CLI도 같은 길을 씁니다. GUI gui/src/components/CodexAccountPool.tsx는 openReauth(id)로 모달을 열고, gui/src/components/use-add-codex-account-oauth.ts가 { id, reauth: true }로 로그인 API를 호출합니다. 카드/배너의 “Re-authenticate” 버튼(codex-account-pool-cards.tsx)이 그 진입점입니다. CLI는 ocx account login … --reauth / ocx account reauth(src/cli/account-auth.ts)입니다. 그래서 운영자가 추가(Add) 흐름으로 같은 계정을 또 넣으려 하면 충돌 문구가 뜨는 것이 맞고, 재인증(Re-authenticate) 흐름을 쓰면 본문이 그린 목표(토큰만 갱신, 풀 id·설정 유지)에 가깝게 동작합니다. 2.49.0 마감 트레인(#4067 직후)에서 새로 큰 기능을 열 이슈가 아니라, “이미 있는 길을 못 찾은 요청”에 가깝습니다.
남는 구멍은 작습니다. (1) 추가 흐름의 충돌 메시지가 “재인증 버튼을 쓰라”고 안내하지 않아, 본문처럼 삭제 우회로만 떠올릴 수 있습니다. (2) 재인증인데 풀에 chatgptAccountId도 이메일도 없으면 auth-api.ts가 “Cannot verify account identity for reauth”로 거절합니다. 빈 슬롯·깨진 자격은 의도적으로 조용히 덮어쓰지 않습니다. (3) 로그인 성공 후 warmup이 실패하면 #3846처럼 등록/갱신이 막힐 수 있어, “재인증 버튼은 눌렀는데 실패”로 느껴질 수 있습니다. 그건 이 이슈의 collision 하드블록과는 다른 버그 축입니다. (4) #3898 headless native main reauth는 풀 계정 CTA로는 안 풀립니다.
src/codex/auth-collision.tscheckAccountIdCollision - 네 번째 excludeAccountId로 재인증 슬롯을 건너뛴다. “이미 풀에 있음”은 신규 추가에만 해당하는 가드다. src/codex/auth-api.tsPOST /api/codex-auth/loginreauth - id 필수, 풀에 없는 id면 404. 같은 ChatGPT id(또는 이메일이 있을 때 이메일)만 허용한 뒤 자격만 덮어쓴다. src/codex/auth-api.ts 정체 확인 실패 분기 - id·이메일이 둘 다 없으면 재인증 거절. 잘못된 계정으로 슬롯을 바꾸는 사고를 막는다. gui/.../use-add-codex-account-oauth.ts - 재인증 때 { id, reauth: true }와 login-status reauth=1. Add와 경로가 갈라진다. gui/.../codex-account-pool-cards.tsx / CodexAccountPool.tsx - needs-reauth 카드·배너에 Re-authenticate CTA가 있다. src/cli/account-auth.ts - ocx account reauth / --reauth가 같은 API를 탄다.
경로 Account is already in the pool 문구 - 신규 충돌에만 나오고, 재인증 안내 문장은 없다. 발견성(UX/카피) 문제이지, API 부재는 아니다.
메인테이너의 판단이 필요한 지점
기능을 새로 만들지 말고 이미 출하됨으로 닫을지, 아니면 충돌 오류에 “Re-authenticate / ocx account reauth --id …를 쓰라” 한 줄을 넣는 작은 UX 이슈로 다시 열지
너의 추천 닫으세요(이미 dev에 재인증 경로 있음). 작성자에게는 Providers Codex 풀 카드의 Re-authenticate, 또는 ocx account reauth --id <pool-id>를 안내하면 됩니다. “Add account”로 같은 ChatGPT를 또 넣으면 충돌이 정상입니다. 만약 Re-authenticate를 썼는데도 막혔다면, 그 오류 문구·warmup 실패·headless main 여부를 새 댓글/이슈로 쪼개 주세요(#3846·#3898과 섞지 말 것). types/config 분할 무관, close-don't-rebase 대상 아님. 충돌 메시지에 재인증 안내를 넣고 싶으면 별도 초소형 PR만 받으면 됩니다.
Thanks for the detailed write-up. The in-place re-authentication you describe already ships on dev (8026405) — it is just on a different entry point from Add account.
checkAccountIdCollision takes a fourth excludeAccountId argument (src/codex/auth-collision.ts:94,99), and POST /api/codex-auth/login passes the target pool id when reauth: true is set (src/codex/auth-api.ts:2629-2632,2751), so the collision check skips that slot and only the credential is overwritten. The pool id is kept stable and the re-auth quarantine is cleared on success (src/codex/auth-api.ts:2803-2807), so usage history, alias, and routing settings survive.
In the dashboard, use the Re-authenticate action on the account card (gui/src/components/CodexAccountPool.tsx:189); from the CLI, run ocx account reauth --id <pool-id> (src/cli/account-auth.ts:282). The collision error is the correct answer for Add account, because that path must not silently replace a different account's credential.
Closing as already supported. If you did use Re-authenticate and it still failed, please open a new report with the exact error text — that would be a different defect (warmup coupling is tracked in #3846, headless native-main recovery in #3898).
Activity
lidge-jun commentedon Sep 8, 2026
리뷰 · 우선순위 34 / 80
설명
이 이슈는 Codex 풀 계정이 만료·세션 끊김으로 못 쓰일 때, 같은 ChatGPT 계정으로 다시 로그인하면
checkAccountIdCollision이 “Account is already in the pool”로 막고, 그래서 풀에서 지운 뒤 다시 넣어야 해서 사용 기록·우선순위·라벨이 사라진다는 요청입니다. 작성자nordz0r, 라벨은enhancement+account-pool입니다. 관련로 본문이 적은 #3375(풀 라이프사이클)·#3846(등록이 warmup 성공에 묶임)은 아직 열려 있고, 비슷한 축의 #3898은 네이티브 main(__main__)을 headless 허브 WebUI에서 reauth하는 별 문제라 이 이슈와 같지 않습니다. 지금 로컬devHEAD는8026405d9(#4067 wp7 프록시 stop 거절 사유), package 2.49.0입니다. types.ts/config.ts 분할·preview 배포와는 무관합니다. 이 번호로 열린 구현 PR은 없습니다.왜 우선순위가 낮은가. 요청한 “제자리 재인증”은 이미 현재
dev에 들어가 있습니다. 새 계정 추가 경로만 보면 본문 설명이 맞습니다.src/codex/auth-collision.ts의checkAccountIdCollision은 같은 개인/워크스페이스 버킷 안에서 같은chatgptAccountId(그리고 이메일이 있으면 같은 이메일)를 보면 충돌로 끝냅니다. 그런데 네 번째 인자excludeAccountId가 있고, 재인증일 때는 그 슬롯을 건너뜁니다.src/codex/auth-api.ts의POST /api/codex-auth/login은 body에reauth: true와 풀id가 오면 재인증 모드로 갑니다. 같은 ChatGPT 정체인지 확인한 뒤, 충돌 검사에서 그id를 빼고, 자격 증명을 그 풀 id 위에 덮어씁니다. 성공하면clearAccountNeedsReauth로 격리도 풉니다. 풀 행 id는 그대로라서, 본문이 걱정한 “지우고 다시 넣기”로 히스토리가 날아가는 경로를 피할 수 있게 이미 설계되어 있습니다.화면과 CLI도 같은 길을 씁니다. GUI
gui/src/components/CodexAccountPool.tsx는openReauth(id)로 모달을 열고,gui/src/components/use-add-codex-account-oauth.ts가{ id, reauth: true }로 로그인 API를 호출합니다. 카드/배너의 “Re-authenticate” 버튼(codex-account-pool-cards.tsx)이 그 진입점입니다. CLI는ocx account login … --reauth/ocx account reauth(src/cli/account-auth.ts)입니다. 그래서 운영자가 추가(Add) 흐름으로 같은 계정을 또 넣으려 하면 충돌 문구가 뜨는 것이 맞고, 재인증(Re-authenticate) 흐름을 쓰면 본문이 그린 목표(토큰만 갱신, 풀 id·설정 유지)에 가깝게 동작합니다. 2.49.0 마감 트레인(#4067 직후)에서 새로 큰 기능을 열 이슈가 아니라, “이미 있는 길을 못 찾은 요청”에 가깝습니다.남는 구멍은 작습니다. (1) 추가 흐름의 충돌 메시지가 “재인증 버튼을 쓰라”고 안내하지 않아, 본문처럼 삭제 우회로만 떠올릴 수 있습니다. (2) 재인증인데 풀에
chatgptAccountId도 이메일도 없으면auth-api.ts가 “Cannot verify account identity for reauth”로 거절합니다. 빈 슬롯·깨진 자격은 의도적으로 조용히 덮어쓰지 않습니다. (3) 로그인 성공 후 warmup이 실패하면 #3846처럼 등록/갱신이 막힐 수 있어, “재인증 버튼은 눌렀는데 실패”로 느껴질 수 있습니다. 그건 이 이슈의 collision 하드블록과는 다른 버그 축입니다. (4) #3898 headless native main reauth는 풀 계정 CTA로는 안 풀립니다.src/codex/auth-collision.tscheckAccountIdCollision- 네 번째excludeAccountId로 재인증 슬롯을 건너뛴다. “이미 풀에 있음”은 신규 추가에만 해당하는 가드다.src/codex/auth-api.tsPOST /api/codex-auth/loginreauth-id필수, 풀에 없는 id면 404. 같은 ChatGPT id(또는 이메일이 있을 때 이메일)만 허용한 뒤 자격만 덮어쓴다.src/codex/auth-api.ts정체 확인 실패 분기 - id·이메일이 둘 다 없으면 재인증 거절. 잘못된 계정으로 슬롯을 바꾸는 사고를 막는다.gui/.../use-add-codex-account-oauth.ts- 재인증 때{ id, reauth: true }와 login-statusreauth=1. Add와 경로가 갈라진다.gui/.../codex-account-pool-cards.tsx/CodexAccountPool.tsx- needs-reauth 카드·배너에 Re-authenticate CTA가 있다.src/cli/account-auth.ts-ocx account reauth/--reauth가 같은 API를 탄다.경로
Account is already in the pool문구 - 신규 충돌에만 나오고, 재인증 안내 문장은 없다. 발견성(UX/카피) 문제이지, API 부재는 아니다.메인테이너의 판단이 필요한 지점
ocx account reauth --id …를 쓰라” 한 줄을 넣는 작은 UX 이슈로 다시 열지너의 추천
닫으세요(이미
dev에 재인증 경로 있음). 작성자에게는 Providers Codex 풀 카드의 Re-authenticate, 또는ocx account reauth --id <pool-id>를 안내하면 됩니다. “Add account”로 같은 ChatGPT를 또 넣으면 충돌이 정상입니다. 만약 Re-authenticate를 썼는데도 막혔다면, 그 오류 문구·warmup 실패·headless main 여부를 새 댓글/이슈로 쪼개 주세요(#3846·#3898과 섞지 말 것). types/config 분할 무관, close-don't-rebase 대상 아님. 충돌 메시지에 재인증 안내를 넣고 싶으면 별도 초소형 PR만 받으면 됩니다.이 댓글은 grok-bot이 작성했습니다
lidge-jun commentedon Sep 9, 2026
Thanks for the detailed write-up. The in-place re-authentication you describe already ships on
dev(8026405) — it is just on a different entry point from Add account.checkAccountIdCollisiontakes a fourthexcludeAccountIdargument (src/codex/auth-collision.ts:94,99), andPOST /api/codex-auth/loginpasses the target pool id whenreauth: trueis set (src/codex/auth-api.ts:2629-2632,2751), so the collision check skips that slot and only the credential is overwritten. The pool id is kept stable and the re-auth quarantine is cleared on success (src/codex/auth-api.ts:2803-2807), so usage history, alias, and routing settings survive.In the dashboard, use the Re-authenticate action on the account card (
gui/src/components/CodexAccountPool.tsx:189); from the CLI, runocx account reauth --id <pool-id>(src/cli/account-auth.ts:282). The collision error is the correct answer for Add account, because that path must not silently replace a different account's credential.Closing as already supported. If you did use Re-authenticate and it still failed, please open a new report with the exact error text — that would be a different defect (warmup coupling is tracked in #3846, headless native-main recovery in #3898).