router-for-me/CLIProxyAPI · error
missing access_token and refresh_token
Error message
missing access_token and refresh_token
What it means
In cmd/fetch_codex_models/main.go the tool resolves an access token from an auth file's metadata. If metadata contains neither a usable `access_token` nor a `refresh_token`, there is no credential to present or refresh, so it fails with `missing access_token and refresh_token`. This always indicates the selected auth file is not a completed Codex OAuth credential (or the keys are named differently).
Source
Thrown at cmd/fetch_codex_models/main.go:194
return auth
}
return nil
}
func ensureAccessToken(ctx context.Context, store *sdkauth.FileTokenStore, auth *coreauth.Auth) (string, bool, error) {
accessToken := metaStringValue(auth.Metadata, "access_token")
if accessToken != "" {
if expiresAt, ok := auth.ExpirationTime(); !ok || time.Now().Add(accessTokenRefreshLeeway).Before(expiresAt) {
return accessToken, false, nil
}
}
refreshToken := metaStringValue(auth.Metadata, "refresh_token")
if refreshToken == "" {
if accessToken != "" {
return accessToken, false, nil
}
return "", false, fmt.Errorf("missing access_token and refresh_token")
}
svc := codexauth.NewCodexAuthWithProxyURL(nil, auth.ProxyURL)
tokenData, errRefresh := svc.RefreshTokensWithRetry(ctx, refreshToken, 3)
if errRefresh != nil {
return "", false, errRefresh
}
if strings.TrimSpace(tokenData.AccessToken) == "" {
return "", false, fmt.Errorf("refresh response did not include access_token")
}
if auth.Metadata == nil {
auth.Metadata = make(map[string]any)
}
auth.Metadata["id_token"] = tokenData.IDToken
auth.Metadata["access_token"] = tokenData.AccessToken
if tokenData.RefreshToken != "" {
auth.Metadata["refresh_token"] = tokenData.RefreshTokenView on GitHub (pinned to 78f0c4079e)
Solutions
- Re-authenticate Codex via the proxy's OAuth login flow so auths/<file>.json contains a full metadata block with access_token/refresh_token.
- Verify the JSON structure: tokens must live under `metadata.access_token` / `metadata.refresh_token`, not at the top level.
- Confirm the auth file type is codex (`metadata.type: "codex"`) and not another provider's credential.
- Point --auth at the correct file in auths/ generated by a successful login.
Example fix
// before: incomplete auth file
{ "id": "my-auth", "type": "codex" }
// after: complete auth file
{
"id": "my-auth",
"type": "codex",
"metadata": {
"access_token": "...",
"refresh_token": "...",
"type": "codex"
}
} Defensive patterns
Strategy: validation
Validate before calling
// Run before invoking the tool/SDK with an auth file
func authHasCodexTokens(authJSON []byte) bool {
meta := gjson.GetBytes(authJSON, "metadata")
return meta.Get("access_token").String() != "" || meta.Get("refresh_token").String() != ""
} Type guard
func isUsableCodexAuth(meta map[string]any) bool {
at, _ := meta["access_token"].(string)
rt, _ := meta["refresh_token"].(string)
return strings.TrimSpace(at) != "" || strings.TrimSpace(rt) != ""
} Prevention
- Validate the auth file structure (tokens under metadata) before passing it to fetch_codex_models.
- Always mint credentials via the proxy's OAuth login flow rather than hand-writing files.
- Check metadata.type == "codex" to avoid feeding other providers' files to the tool.
When it happens
Trigger: Running fetch_codex_models with --auth pointing at a JSON file whose metadata lacks both `access_token` and `refresh_token` keys: a hand-written stub file, a partially completed login, an auth file of a different provider type (e.g. Gemini/Qwen), or metadata keys misspelled.
Common situations: Reusing an auths/ file from another provider; login flow interrupted before tokens were persisted; manually edited auth JSON that dropped the metadata block; file-level key expected at top level instead of under `metadata`.
Related errors
- refresh response did not include access_token
- failed to save refreshed auth: %w
- models request failed with status %d: %s
- response JSON does not contain models array
- port %d is already in use
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/b698e0ae1487aab1.
Report an issue: GitHub.