cli/cli · error
invalid branch name: %q
Error message
invalid branch name: %q
What it means
Guard in `gh pr checkout` that rejects a PR head ref name beginning with '-'. The head ref comes from the remote PR data and is passed to git commands (fetch/checkout/worktree add) as an argument; a leading dash would be parsed as an option, so the command refuses before shelling out. This is an option-injection defense, not a general validity check.
Source
Thrown at pkg/cmd/pr/checkout/checkout.go:155
remotes, err := opts.Remotes()
if err != nil {
return err
}
baseRemote, _ := remotes.FindByRepo(baseRepo.RepoOwner(), baseRepo.RepoName())
baseURLOrName := ghrepo.FormatRemoteURL(baseRepo, protocol)
if baseRemote != nil {
baseURLOrName = baseRemote.Name
}
headRemote := baseRemote
if pr.HeadRepository == nil {
headRemote = nil
} else if pr.IsCrossRepository {
headRemote, _ = remotes.FindByRepo(pr.HeadRepositoryOwner.Login, pr.HeadRepository.Name)
}
if strings.HasPrefix(pr.HeadRefName, "-") {
return fmt.Errorf("invalid branch name: %q", pr.HeadRefName)
}
var cmdQueue [][]string
if headRemote != nil {
cmdQueue = append(cmdQueue, cmdsForExistingRemote(headRemote, pr, opts, reuseWorktree)...)
} else {
httpClient, err := opts.HttpClient()
if err != nil {
return err
}
apiClient := api.NewClientFromHTTP(httpClient)
defaultBranch, err := api.RepoDefaultBranch(apiClient, baseRepo)
if err != nil {
return err
}
cmdQueue = append(cmdQueue, cmdsForMissingRemote(pr, baseURLOrName, baseRepo.RepoHost(), defaultBranch, protocol, opts, reuseWorktree)...)View on GitHub (pinned to 0eeec0b92e)
Solutions
- Do not check out that PR by branch name; fetch and check it out by ref instead: `git fetch origin pull/<N>/head && git checkout FETCH_HEAD`.
- Ask the PR author to rename the branch to a name not starting with '-' and update the PR.
- If you administer the source repo, reject branch names starting with '-' at the server/push level.
Example fix
# before gh pr checkout 57 # head branch '-rf' -> invalid branch name # after git fetch origin pull/57/head git checkout FETCH_HEAD
Defensive patterns
Strategy: validation
Validate before calling
# inspect the PR head branch before checkout head=$(gh pr view "$N" --json headRefName --jq .headRefName) case "$head" in -*) echo "refusing dash-prefixed branch: $head" >&2; exit 2;; esac gh pr checkout "$N"
Prevention
- Fetch by PR ref instead of branch name for untrusted PRs: `git fetch origin pull/N/head && git checkout FETCH_HEAD`.
- Reject branch names starting with '-' in server-side push rules/hooks.
- Treat externally-supplied branch names as untrusted input when building git commands.
When it happens
Trigger: Checking out a PR whose HeadRefName starts with '-' (e.g. a branch named '-rf' or '--force' pushed from another git client). GitHub itself rarely permits such branch names via the web UI, but some git servers/versions accept them, so gh guards locally.
Common situations: PRs opened from forks with adversarial or malformed branch names; ghsec-style hardening after option-injection findings; testing gh against permissive GHE instances.
Related errors
- --worktree path is inside a different repository
- --worktree path points to the repository you're already in;
- --worktree path is inside an existing worktree
- --worktree path must not be a symlink: %s
- couldn't get hosts configuration
AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15).
Data as JSON: /api/errors/6d1140f80bca7296.
Report an issue: GitHub.