nikivdev/code · error

gh login was empty

Error message

gh login was empty

What it means

After a successful `gh api user` call, the trimmed stdout login is checked; if gh reports success but returns an empty login string, this bail fires. It guards against authenticated-but-anonymous or malformed responses.

Source

Thrown at src/repos.rs:1477

fn normalize_git_url(url: &str) -> String {
    url.trim()
        .trim_end_matches('/')
        .trim_end_matches(".git")
        .to_string()
}

fn github_login() -> Result<String> {
    let output = Command::new("gh")
        .args(["api", "user", "-q", ".login"])
        .output()
        .context("failed to run gh api user")?;
    if !output.status.success() {
        bail!("gh api user failed");
    }
    let login = String::from_utf8_lossy(&output.stdout).trim().to_string();
    if login.is_empty() {
        bail!("gh login was empty");
    }
    Ok(login)
}

fn resolve_remote_default_branch_in(repo_root: &Path, remote: &str) -> Option<String> {
    let head_ref = format!("refs/remotes/{remote}/HEAD");
    if let Ok(symbolic) = git_capture_in(repo_root, &["symbolic-ref", &head_ref]) {
        let prefix = format!("refs/remotes/{remote}/");
        if let Some(branch) = symbolic.trim().strip_prefix(&prefix)
            && !branch.is_empty()
        {
            return Some(branch.to_string());
        }
    }

    for candidate in ["main", "master", "dev", "trunk"] {
        if git_ref_exists_in(repo_root, &format!("refs/remotes/{remote}/{candidate}")) {
            return Some(candidate.to_string());

View on GitHub (pinned to a747e741ae)

Solutions

  1. Run `gh api user -q .login` manually to confirm what it prints.
  2. Re-authenticate with `gh auth login` using a user token (PAT/classic OAuth).
  3. Check for wrapper scripts/aliases intercepting `gh` and remove or fix them.

Example fix

// before: empty login from wrapper
$ gh() { echo -n ""; }   # broken wrapper
// after: ensure real gh resolves the login
$ gh api user -q .login   # prints e.g. octocat
Defensive patterns

Strategy: validation

Validate before calling

fn gh_login_resolves() -> bool {
    std::process::Command::new("gh")
        .args(["api", "user", "-q", ".login"])
        .output()
        .map(|o| o.status.success() && !o.stdout.iter().all(|&b| b.is_ascii_whitespace()))
        .unwrap_or(false)
}

Try / catch

match github_login() {
    Err(e) if e.to_string().contains("gh login was empty") => {
        // check for wrappers intercepting gh, or tokens lacking user:read
        eprintln!("gh returned empty login; run: gh auth login");
    }
    r => r?,
}

Prevention

When it happens

Trigger: `gh api user` exits 0 but `.login` is empty/whitespace — e.g. unusual token types (fine-grained/OAuth app tokens) or mocked/filtered gh wrappers returning empty output.

Common situations: Corporate gh wrappers/proxies stripping output; token without permission to read the user profile; piping gh output through filters that drop it.

Related errors


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