{"record":{"id":"41652e96263a9465","repo":"chenhg5/cc-connect","slug":"read-s-w","errorCode":null,"errorMessage":"read %s: %w","messagePattern":"read (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"agent/codex/usage.go","lineNumber":68,"sourceCode":"\tBalance    any  `json:\"balance\"`\n}\n\nfunc (a *Agent) GetUsage(ctx context.Context) (*core.UsageReport, error) {\n\ttokens, err := a.readOAuthTokens(os.ReadFile)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn a.fetchUsage(ctx, http.DefaultClient, tokens)\n}\n\nfunc (a *Agent) readOAuthTokens(readFile func(string) ([]byte, error)) (codexOAuthTokens, error) {\n\tpath, err := codexAuthPath()\n\tif err != nil {\n\t\treturn codexOAuthTokens{}, err\n\t}\n\tdata, err := readFile(path)\n\tif err != nil {\n\t\treturn codexOAuthTokens{}, fmt.Errorf(\"read %s: %w\", path, err)\n\t}\n\n\tvar payload struct {\n\t\tTokens struct {\n\t\t\tAccessToken string `json:\"access_token\"`\n\t\t\tAccountID   string `json:\"account_id\"`\n\t\t} `json:\"tokens\"`\n\t}\n\tif err := json.Unmarshal(data, &payload); err != nil {\n\t\treturn codexOAuthTokens{}, fmt.Errorf(\"parse auth.json: %w\", err)\n\t}\n\tif strings.TrimSpace(payload.Tokens.AccessToken) == \"\" {\n\t\treturn codexOAuthTokens{}, fmt.Errorf(\"auth.json missing tokens.access_token\")\n\t}\n\tif strings.TrimSpace(payload.Tokens.AccountID) == \"\" {\n\t\treturn codexOAuthTokens{}, fmt.Errorf(\"auth.json missing tokens.account_id\")\n\t}\n","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/chenhg5/cc-connect/blob/4000b2338aa6e850c99df54f8b0ed6ed7460b401/agent/codex/usage.go#L50-L86","documentation":"readOAuthTokens loads Codex CLI OAuth credentials from ~/.codex/auth.json (or $CODEX_HOME/auth.json) to authenticate usage-quota queries against the ChatGPT backend. This error wraps the underlying os.ReadFile failure, preserving the file path and OS-level cause (e.g. ENOENT, EACCES). It is thrown whenever the auth.json file cannot be read, which the library treats as a hard failure because usage data cannot be fetched without a token.","triggerScenarios":"GetUsage() -> readOAuthTokens() when readFile(path) fails: the auth.json path does not exist (Codex never logged in), the path is a directory, or the file cannot be opened due to permissions. Callers: GetUsage and the readOAuthTokens tests.","commonSituations":"Running usage queries on a machine where `codex login` was never executed; CODEX_HOME pointing at a nonexistent or wrong directory; running the bridge under a service account (systemd/launchd) whose HOME differs from the user that logged into Codex; restrictive file permissions after copying dotfiles.","solutions":["Run `codex login` to create the auth.json file","Verify the resolved path: check CODEX_HOME, or confirm ~/.codex/auth.json exists (`ls -la $CODEX_HOME/auth.json` or `ls -la ~/.codex/auth.json`)","If running as a daemon/service, set CODEX_HOME (or HOME) to the directory containing the logged-in auth.json","Fix file permissions so the process user can read auth.json (chmod 600, correct owner)"],"exampleFix":"// before: error only visible at runtime\nusage, err := agent.GetUsage(ctx)\n// after: probe the auth file first and give a clear message\nif _, err := os.Stat(filepath.Join(os.Getenv(\"CODEX_HOME\"), \"auth.json\")); os.IsNotExist(err) {\n    log.Fatal(\"codex auth.json not found; run `codex login` first\")\n}\nusage, err := agent.GetUsage(ctx)","handlingStrategy":"validation","validationCode":"p := filepath.Join(os.Getenv(\"CODEX_HOME\"), \"auth.json\")\nif os.Getenv(\"CODEX_HOME\") == \"\" { p = filepath.Join(os.Getenv(\"HOME\"), \".codex\", \"auth.json\") }\nif _, err := os.Stat(p); err != nil { return fmt.Errorf(\"codex auth.json not readable at %s: %w\", p, err) }","typeGuard":null,"tryCatchPattern":"tokens, err := readOAuthTokens()\nif err != nil {\n    var pe *fs.PathError\n    if errors.As(err, &pe) && errors.Is(pe.Err, fs.ErrNotExist) {\n        return fmt.Errorf(\"run `codex login` first (missing %s)\", pe.Path)\n    }\n    return err\n}","preventionTips":["Run `codex login` before enabling usage queries","Set CODEX_HOME explicitly in daemon/service environments","Ensure the service runs as the user owning ~/.codex","Add a startup health check that stats auth.json"],"tags":["go","filesystem","codex","oauth"],"backgroundTag":"file-read-failed","analyzedSha":"4000b2338aa6e850c99df54f8b0ed6ed7460b401","analyzedAt":"2026-09-06T11:45:09.575Z","contentChangedAt":"2026-09-06T11:45:09.575Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}