{"record":{"id":"880bf5f377321bd8","repo":"nikivdev/code","slug":"gh-auth-token-failed-run-gh-auth-login","errorCode":null,"errorMessage":"`gh auth token` failed; run `gh auth login`","messagePattern":"`gh auth token` failed; run `gh auth login`","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/pr_edit.rs","lineNumber":401,"sourceCode":"                },\n                last_digest_hex: None,\n            });\n        entry.public.meta = meta;\n        entry.public.state = SyncState::Error;\n        entry.public.last_error = Some(err);\n    }\n\n    async fn get_gh_token(&self) -> Result<String> {\n        if let Some(t) = self.gh_token.read().await.clone() {\n            return Ok(t);\n        }\n\n        let out = Command::new(\"gh\")\n            .args([\"auth\", \"token\"])\n            .output()\n            .context(\"failed to run `gh auth token`\")?;\n        if !out.status.success() {\n            bail!(\"`gh auth token` failed; run `gh auth login`\");\n        }\n        let token = String::from_utf8_lossy(&out.stdout).trim().to_string();\n        if token.is_empty() {\n            bail!(\"`gh auth token` returned empty token\");\n        }\n\n        *self.gh_token.write().await = Some(token.clone());\n        Ok(token)\n    }\n\n    async fn write_status_json(&self) -> Result<()> {\n        let snapshot = self.status_snapshot().await;\n        let json = serde_json::to_string_pretty(&snapshot)?;\n\n        let tmp = self.dir.join(format!(\".{STATUS_FILENAME}.tmp\"));\n        let out = self.dir.join(STATUS_FILENAME);\n        std::fs::write(&tmp, json)?;\n        // Best-effort atomic replace.","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/pr_edit.rs#L383-L419","documentation":"get_gh_token shells out to `gh auth token` to obtain a GitHub token. When the gh CLI itself exits non-zero, the tool bails with a hint to authenticate, since the gh process reporting failure almost always means the user is not logged in.","triggerScenarios":"sync_file triggers get_gh_token while gh is installed but not authenticated (`gh auth login` never run or token expired/revoked), so `gh auth token` exits with an error status.","commonSituations":"CI containers without gh authentication; after rotating credentials; gh config directory missing or unreadable (GH_CONFIG_DIR points elsewhere).","solutions":["Run `gh auth login` and follow the prompts to authenticate the GitHub CLI.","Verify with `gh auth status` that you are logged in and the token is valid.","In CI, set GH_TOKEN/GITHUB_TOKEN and `gh auth login --with-token` before running the tool."],"exampleFix":"// before\n$ f pr-edit ...\n// `gh auth token` failed; run `gh auth login`\n\n// after\n$ gh auth login\n$ gh auth status  # confirm logged in\n$ f pr-edit ...","handlingStrategy":"try-catch","validationCode":"let status = std::process::Command::new(\"gh\")\n    .args([\"auth\", \"status\"])\n    .status()?;\nif !status.success() {\n    eprintln!(\"gh is not authenticated; run `gh auth login` first\");\n}","typeGuard":null,"tryCatchPattern":"match pr_edit_result {\n    Err(e) if e.to_string().contains(\"gh auth token\") => {\n        eprintln!(\"Authenticate first: gh auth login (or gh auth login --with-token in CI)\");\n    }\n    other => other?,\n}","preventionTips":["Run `gh auth status` before GitHub-dependent commands.","In CI, authenticate gh via GH_TOKEN and `gh auth login --with-token` in setup steps.","Check `gh --version` if failures persist after login (config path issues)."],"tags":["github","auth","cli","gh"],"backgroundTag":"gh-cli-not-authenticated","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}