nikivdev/code · error

`gh auth token` failed; run `gh auth login`

Error message

`gh auth token` failed; run `gh auth login`

What it means

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.

Source

Thrown at src/pr_edit.rs:401

                },
                last_digest_hex: None,
            });
        entry.public.meta = meta;
        entry.public.state = SyncState::Error;
        entry.public.last_error = Some(err);
    }

    async fn get_gh_token(&self) -> Result<String> {
        if let Some(t) = self.gh_token.read().await.clone() {
            return Ok(t);
        }

        let out = Command::new("gh")
            .args(["auth", "token"])
            .output()
            .context("failed to run `gh auth token`")?;
        if !out.status.success() {
            bail!("`gh auth token` failed; run `gh auth login`");
        }
        let token = String::from_utf8_lossy(&out.stdout).trim().to_string();
        if token.is_empty() {
            bail!("`gh auth token` returned empty token");
        }

        *self.gh_token.write().await = Some(token.clone());
        Ok(token)
    }

    async fn write_status_json(&self) -> Result<()> {
        let snapshot = self.status_snapshot().await;
        let json = serde_json::to_string_pretty(&snapshot)?;

        let tmp = self.dir.join(format!(".{STATUS_FILENAME}.tmp"));
        let out = self.dir.join(STATUS_FILENAME);
        std::fs::write(&tmp, json)?;
        // Best-effort atomic replace.

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run `gh auth login` and follow the prompts to authenticate the GitHub CLI.
  2. Verify with `gh auth status` that you are logged in and the token is valid.
  3. In CI, set GH_TOKEN/GITHUB_TOKEN and `gh auth login --with-token` before running the tool.

Example fix

// before
$ f pr-edit ...
// `gh auth token` failed; run `gh auth login`

// after
$ gh auth login
$ gh auth status  # confirm logged in
$ f pr-edit ...
Defensive patterns

Strategy: try-catch

Validate before calling

let status = std::process::Command::new("gh")
    .args(["auth", "status"])
    .status()?;
if !status.success() {
    eprintln!("gh is not authenticated; run `gh auth login` first");
}

Try / catch

match pr_edit_result {
    Err(e) if e.to_string().contains("gh auth token") => {
        eprintln!("Authenticate first: gh auth login (or gh auth login --with-token in CI)");
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: CI containers without gh authentication; after rotating credentials; gh config directory missing or unreadable (GH_CONFIG_DIR points elsewhere).

Related errors


AI-assisted analysis of nikivdev/code@a747e741ae (2026-09-01). Data as JSON: /api/errors/880bf5f377321bd8. Report an issue: GitHub.