router-for-me/CLIProxyAPI · error
fetch Claude OAuth %s: access token is empty
Error message
fetch Claude OAuth %s: access token is empty
What it means
Returned by ClaudeAuth.fetchOAuthControlPlaneJSON when the access token, after strings.TrimSpace, is empty. This is a precondition check before any network activity: the caller passed "" (or whitespace) for the token on a profile/roles fetch. It means upstream state (the stored credential) had no access token at the point of use — typically an empty token file, a failed refresh whose error was swallowed, or a caller passing the wrong variable.
Source
Thrown at internal/auth/claude/anthropic_auth.go:231
return
}
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("User-Agent", "axios/1.15.2")
req.Header.Set("Accept-Encoding", "gzip, compress, deflate, br")
req.Header.Set("Connection", "close")
req.Close = true
}
// fetchOAuthControlPlaneJSON issues an Axios-shaped OAuth control-plane GET and
// returns the decoded response body. label names the endpoint in error text.
func (o *ClaudeAuth) fetchOAuthControlPlaneJSON(ctx context.Context, endpoint, accessToken, label string) ([]byte, error) {
if o == nil || o.httpClient == nil {
return nil, fmt.Errorf("fetch Claude OAuth %s: HTTP client is nil", label)
}
accessToken = strings.TrimSpace(accessToken)
if accessToken == "" {
return nil, fmt.Errorf("fetch Claude OAuth %s: access token is empty", label)
}
req, errRequest := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if errRequest != nil {
return nil, fmt.Errorf("create Claude OAuth %s request: %w", label, errRequest)
}
applyClaudeOAuthAxiosHeaders(req)
req.Header.Set("Authorization", "Bearer "+accessToken)
req.Header.Set("Cache-Control", "no-cache")
resp, errDo := o.httpClient.Do(req)
if errDo != nil {
return nil, fmt.Errorf("fetch Claude OAuth %s: %w", label, errDo)
}
defer func() {
if errClose := resp.Body.Close(); errClose != nil {
log.Errorf("failed to close Claude OAuth %s response body: %v", label, errClose)
}
}()View on GitHub (pinned to 78f0c4079e)
Solutions
- Ensure the access token is refreshed (RefreshToken flow) before calling profile/roles fetches, and propagate refresh errors instead of ignoring them
- Inspect the stored Claude credential file under auths/ — if access_token is empty, delete it and re-run the Claude OAuth login
- Add a call-site check: skip the fetch when strings.TrimSpace(token) == "" and trigger refresh instead
Example fix
// before
profile, err := auth.FetchOAuthProfile(ctx, "") // guard fires
// after
if strings.TrimSpace(token) == "" {
token, err = auth.RefreshToken(ctx)
if err != nil { return err }
}
profile, err := auth.FetchOAuthProfile(ctx, token) Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(accessToken) == "" {
return fmt.Errorf("access token empty; run token refresh before profile/roles fetch")
} Type guard
func hasClaudeToken(token string) bool {
return strings.TrimSpace(token) != ""
} Try / catch
if !hasClaudeToken(token) { token, err = auth.RefreshToken(ctx); if err != nil { return err } }
profile, err := auth.FetchOAuthProfile(ctx, token) Prevention
- Refresh tokens before every profile/roles fetch and propagate refresh errors
- Re-run the Claude OAuth login when the stored credential file has an empty access_token
When it happens
Trigger: Calling FetchOAuthProfile/FetchOAuthRoles with an empty accessToken; a token store entry under auths/ whose access_token field is blank because a prior refresh failed silently.
Common situations: Corrupted or hand-edited Claude credential JSON files; refresh-token flow producing a response without access_token that was persisted anyway; code that reads the token before refresh completes.
Related errors
- antigravity userinfo: missing access token
- fetch Claude OAuth %s: HTTP client is nil
- fetch Claude OAuth %s: %w
- read Claude OAuth %s response: %w
- select Claude device ID: session ID is empty
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/031351dc76a651fd.
Report an issue: GitHub.