chenhg5/cc-connect · error

auth.json missing tokens.account_id

Error message

auth.json missing tokens.account_id

What it means

readOAuthTokens requires a non-empty tokens.account_id in auth.json; this error is thrown when the JSON parses but account_id is missing, empty, or whitespace-only. The account id is sent as the ChatGPT-Account-Id header on usage requests, so without it the library cannot query the correct account and fails before making the request.

Source

Thrown at agent/codex/usage.go:84

	data, err := readFile(path)
	if err != nil {
		return codexOAuthTokens{}, fmt.Errorf("read %s: %w", path, err)
	}

	var payload struct {
		Tokens struct {
			AccessToken string `json:"access_token"`
			AccountID   string `json:"account_id"`
		} `json:"tokens"`
	}
	if err := json.Unmarshal(data, &payload); err != nil {
		return codexOAuthTokens{}, fmt.Errorf("parse auth.json: %w", err)
	}
	if strings.TrimSpace(payload.Tokens.AccessToken) == "" {
		return codexOAuthTokens{}, fmt.Errorf("auth.json missing tokens.access_token")
	}
	if strings.TrimSpace(payload.Tokens.AccountID) == "" {
		return codexOAuthTokens{}, fmt.Errorf("auth.json missing tokens.account_id")
	}

	return codexOAuthTokens{
		AccessToken: payload.Tokens.AccessToken,
		AccountID:   payload.Tokens.AccountID,
	}, nil
}

func (a *Agent) fetchUsage(ctx context.Context, client *http.Client, tokens codexOAuthTokens) (*core.UsageReport, error) {
	req, err := http.NewRequestWithContext(ctx, http.MethodGet, codexUsageURL, nil)
	if err != nil {
		return nil, err
	}
	req.Header.Set("Authorization", "Bearer "+tokens.AccessToken)
	req.Header.Set("ChatGPT-Account-Id", tokens.AccountID)
	req.Header.Set("User-Agent", "codex-cli")

	resp, err := client.Do(req)

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Re-run `codex login` with a current Codex CLI so account_id is populated
  2. Inspect auth.json: confirm tokens.account_id exists and is non-empty
  3. Upgrade (or match) the Codex CLI version used to create auth.json to one that writes account_id
  4. If hand-copying credentials, include the complete tokens object

Example fix

// before
// assumes account_id present
usage, err := agent.GetUsage(ctx)
// after: pre-check
var a struct{ Tokens struct{ AccountID string `json:"account_id"` } `json:"tokens"` }
if json.Unmarshal(authBytes, &a) == nil && strings.TrimSpace(a.Tokens.AccountID) == "" {
    log.Fatal("auth.json lacks tokens.account_id; re-run `codex login` with latest codex CLI")
}
usage, err := agent.GetUsage(ctx)
Defensive patterns

Strategy: validation

Validate before calling

var a struct{ Tokens struct{ AccountID string `json:"account_id"` } `json:"tokens"` }
json.Unmarshal(b, &a)
if strings.TrimSpace(a.Tokens.AccountID) == "" { return errors.New("missing tokens.account_id; re-run `codex login`") }

Try / catch

if _, err := agent.GetUsage(ctx); err != nil && strings.Contains(err.Error(), "missing tokens.account_id") {
    log.Println("Codex auth.json predates account_id — update codex CLI and re-login")
}

Prevention

When it happens

Trigger: json.Unmarshal succeeds but strings.TrimSpace(payload.Tokens.AccountID) == "" — auth.json tokens object lacks account_id. Detected by TestReadOAuthTokens_MissingFields and surfaced through GetUsage.

Common situations: Personal-only ChatGPT logins or older Codex CLI versions whose auth.json did not include account_id; hand-assembled auth.json missing the field; schema drift after a Codex CLI upgrade/downgrade; a partially written tokens object.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/386f46a482b0083d. Report an issue: GitHub.