25 lines
1.3 KiB
Markdown
25 lines
1.3 KiB
Markdown
---
|
|
description: How codex, claude, and opencode report rejected credentials, and how the runner detects them
|
|
---
|
|
|
|
Observed 2026-10 (codex 0.153/0.162, Claude Code 2.1.28x, opencode 1.18/1.19):
|
|
|
|
- Codex: `codex login status` only reads the local auth.json, so a
|
|
server-revoked ChatGPT login passes it. `codex exec` then exits 1 with stderr
|
|
ERROR lines such as `refresh_token_invalidated` / "Your session has ended.
|
|
Please log in again.", `auth error code: token_revoked`, `401 Unauthorized`; a
|
|
bad API key gives `invalid_api_key`. Codex echoes the whole prompt and tool
|
|
output to stderr, so `isCodexAuthFailure` only matches ERROR lines and the
|
|
runner strips the prompt first.
|
|
- Claude: a bad `CLAUDE_CODE_OAUTH_TOKEN` yields a stream-json `result` with
|
|
`is_error: true`, `api_error_status: 401`, and "Failed to authenticate. API
|
|
Error: 401 OAuth access token is invalid."; exit code 1, empty stderr.
|
|
- OpenCode: a bad OpenRouter key exits 1 with empty stderr and a stdout JSON
|
|
event
|
|
`{"type":"error","error":{"name":"APIError","data":{"statusCode":401,
|
|
"message":"User not found."}}}`.
|
|
An empty key gives an opaque UnknownError.
|
|
|
|
Sign-in failures become `AgentAuthError` and fall through to the next profile
|
|
like usage exhaustion; the failure comment lists only fixed labels per profile.
|