Fix: gh CLI Not Working — Auth Scopes, Multiple Accounts, PR Create Errors, and Enterprise Hosts
Quick Answer
How to fix GitHub CLI errors — gh auth login token scopes missing, multiple accounts switching, gh pr create permission denied, GHE host auth, gh repo clone vs git clone, and API rate limits.
The Error
You run a perfectly normal gh pr create and get this:
$ gh pr create
HTTP 403: Resource not accessible by integrationOr a fresh gh auth login succeeds but later commands fail:
$ gh repo view org/private-repo
GraphQL: Could not resolve to a Repository with the name 'org/private-repo'Or you have two GitHub accounts (personal + work) and gh keeps using the wrong one:
$ gh pr create
Pushing to your personal fork instead of the work org.Or gh works on macOS but fails in CI:
$ gh release create v1.0.0
gh: To get started with GitHub CLI, please run: gh auth loginWhy This Happens
The GitHub CLI wraps the REST and GraphQL APIs. Most failures map to one of these layers:
- Token scopes.
gh auth loginissues an OAuth token with a fixed set of scopes. Commands that need more scopes (like creating PRs across forks, or releasing) fail with 403 until you re-auth with the right scopes. - Multiple hosts. gh tracks
github.comand any GitHub Enterprise hosts separately.gh auth statusshows which host is active. A command run against the wrong host fails to find resources that exist on the other one. - Multiple accounts on the same host. Recent gh versions support multiple accounts per host with
gh auth switch. Older versions force one account at a time. The active account is what every command runs as. - CI/Actions auth is different. In GitHub Actions,
GITHUB_TOKENandGH_TOKENenv vars override interactive auth. The token’s permissions are set in the workflowpermissions:block.
Fix 1: Re-Auth With the Right Scopes
Default gh auth login covers basic repo operations. For releases, workflows, gists, and other features, ask for additional scopes:
gh auth refresh -s read:org,workflow,write:packagesTo see what you currently have:
gh auth status
# github.com
# ✓ Logged in to github.com as you (oauth_token)
# ✓ Git operations for github.com configured to use https protocol.
# ✓ Token: gho_***
# ✓ Token scopes: 'gist', 'read:org', 'repo', 'workflow'Common scope requirements:
repo— read/write to private repos. Default for most setups.workflow— edit GitHub Actions workflow files. Needed bygh workflowandgh run.read:org— read team/org membership. Needed for SSO-protected resources.write:packages/read:packages— GitHub Packages.delete_repo— delete repos. Off by default for safety.gist— create/manage gists. Needed bygh gist.admin:public_key— manage SSH keys viagh ssh-key.
Pro Tip: Don’t ask for admin:* scopes unless a specific command needs them. Tokens with admin scopes are higher-risk if leaked. Refresh later with -s when a command actually requires more.
Fix 2: Authorize SAML / SSO
For organizations using SAML SSO (most enterprises), even a valid token can’t access org repos until you authorize the token:
GraphQL: Resource protected by organization SAML enforcement.
You must grant your OAuth token access to this organization.The fix is to visit:
https://github.com/orgs/<org-name>/sso?authorization_request=<token-id>gh prints this URL when SSO fails — open it, click Authorize, and your token is now linked. The link persists per token, so you only need to do it once per re-auth.
For private CLI workflows in SSO-required orgs, generate a Personal Access Token at github.com → Settings → Developer settings → PAT, and explicitly authorize it for the org. Set GH_TOKEN env var to use it:
export GH_TOKEN=ghp_...
gh repo view org/private-repo # Now works.Fix 3: Switch Between Multiple Accounts
If you have personal and work GitHub accounts, gh auth login again to add the second:
gh auth login # Pick the second account.
gh auth status
# github.com
# ✓ Logged in to github.com as work-account (oauth_token) - active account
# ✓ Logged in to github.com as personal-account (oauth_token)Switch the active account:
gh auth switch -u personal-accountOr run a single command as a specific user:
gh auth switch -u work-account
gh pr create --base main --head feature
gh auth switch -u personal-accountCommon Mistake: Running gh repo clone while authenticated as the wrong account. The clone URL gets set to that account’s HTTPS credentials and future git push operations use them. Fix the remote URL or re-clone after switching.
Fix 4: GitHub Enterprise Hosts
For GHE Server, log in with the host flag:
gh auth login --hostname github.example.comgh stores credentials per host in ~/.config/gh/hosts.yml. To run a command against a specific host:
gh --hostname github.example.com repo listOr set the default for the current shell:
export GH_HOST=github.example.com
gh repo listFor GHE Cloud with Enterprise Cloud (the newer tier), use the regular github.com host but ensure your token has the enterprise-required scopes.
Note: GHE versions older than the gh CLI may not support the latest GraphQL fields. If gh commands fail with cryptic GraphQL errors on GHE, downgrade gh or check the GHE API version compatibility matrix.
Fix 5: gh pr create Permissions
The most common 403 on gh pr create is creating a PR from a fork. Two scenarios:
You have write access to the upstream repo:
git remote -v
# origin: [email protected]:you/fork.git (push)
# upstream: [email protected]:org/repo.git
# Set upstream as the PR target:
gh pr create --repo org/repo --base main --head you:feature-xYou don’t have write access — fork-and-PR workflow:
gh repo fork org/repo --clone
cd repo
git checkout -b feature-x
# ... commits ...
git push origin feature-x
gh pr create # gh detects the fork and creates PR against upstream.For GitHub Actions creating PRs:
# .github/workflows/pr.yml
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- run: gh pr create --title "Auto PR" --body "..." --base main
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}Without pull-requests: write in permissions, the default GITHUB_TOKEN can’t create PRs.
Fix 6: HTTPS vs SSH and gh repo clone
gh repo clone uses the protocol you set during gh auth login. Check:
gh config get git_protocol
# ssh (or "https")
# Change globally:
gh config set git_protocol ssh
gh config set git_protocol httpsThe protocol controls how gh repo clone writes the origin URL. For SSH, you also need a deploy key set up on GitHub (gh ssh-key add ~/.ssh/id_ed25519.pub).
For mixed setups (HTTPS for some hosts, SSH for others), use git’s insteadOf:
git config --global url."[email protected]:".insteadOf "https://github.com/"Now even an HTTPS URL gets rewritten to SSH at push time. gh itself still uses HTTPS for API calls — which is correct, those go to a different endpoint.
Fix 7: CI/Actions Auth
In GitHub Actions, the default authentication is the auto-generated GITHUB_TOKEN. Two things:
- Set
GH_TOKENenv var so the gh CLI picks it up:
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}- Set the workflow
permissionsfor whatGITHUB_TOKENshould allow:
permissions:
contents: read
pull-requests: write
issues: writeBy default, GITHUB_TOKEN has minimum permissions (read-only). For cross-repo work or admin tasks, use a PAT in secrets.MY_PAT:
env:
GH_TOKEN: ${{ secrets.MY_PAT }}Pro Tip: For multi-repo automation, prefer a fine-grained PAT or a GitHub App over a classic PAT. Fine-grained PATs scope to specific repos and have separate permissions per resource — much safer if leaked.
Fix 8: API Rate Limits
gh respects GitHub’s rate limit. Authenticated requests get 5000/hour; unauthenticated get 60/hour. To check:
gh api rate_limit | jq '.rate'
# {
# "limit": 5000,
# "remaining": 4983,
# "reset": 1716123456,
# "used": 17
# }If you’re hitting the limit:
- Cache responses. For repeated queries, save the result locally and re-use.
- Use GraphQL. A single GraphQL call counts as one request but can fetch what would take dozens of REST calls.
- Use a GitHub App. Apps have higher rate limits scaled by installation count.
For bulk operations, pace with sleep or batch via gh api --paginate:
gh api --paginate -X GET /repos/org/repo/issues -q '.[].number' > all_issues.txt--paginate follows the Link: <next> header automatically, fetching all pages.
Still Not Working?
A few less-obvious failures:
gh auth loginopens browser but token never lands. Firewall blocks the localhost callback. Usegh auth login --with-token < token.txtand paste a PAT instead.- WSL or Codespaces: browser-based login fails. Use
--deviceflow:gh auth login --device. Prints a code; visit github.com/login/device on any browser. gh extension installfails with “not a directory”. You need git installed and a working PATH. gh extensions are git-cloned under the hood.- gh works locally but fails in Docker. No browser available. Mount
~/.config/ghfrom host, or useGH_TOKENdirectly. gh release uploadfails on large files. Default timeout is 30s. Pass--clobberand consider uploading viagh apiwith a manual multipart workflow.gh pr list --search "..."returns weird results. The search query syntax is GitHub’s, not gh’s. See github.com/search/advanced for valid qualifiers.- Custom domain on enterprise: SSL errors. Self-signed corporate certs need the CA installed in your system trust store. gh (a Go binary) honors
SSL_CERT_FILE/SSL_CERT_DIRfor an alternative CA bundle in dev. For production machines, install the CA into the OS trust store instead of env-var workarounds. ghandgitdisagree about credentials. gh uses~/.config/ghfor API auth; git uses credential helpers. Sync them with:gh auth setup-git. This installs gh as a git credential helper.
For related GitHub workflow and authentication issues, see Git permission denied publickey, GitHub Actions permission denied, GitHub Actions secret not available, and Git credential helper not working.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: ArgoCD Not Working — OutOfSync, Sync Waves, RBAC, Helm/Kustomize, and Webhook Setup
How to fix ArgoCD errors — application stuck OutOfSync, sync waves not respected, RBAC permission denied, Helm values not merged, ApplicationSet generator config, repo auth, and webhook not triggering.
Fix: Lefthook Not Working — Install, Staged Files, Glob Filters, Parallel Runs, and CI Skip
How to fix Lefthook errors — hooks not running after install, {staged_files} empty for new files, glob filter not matching, parallel: true ordering, LEFTHOOK=0 to skip in CI, and lefthook-local.yml overrides.
Fix: Git Hooks Not Running — Husky Not Working, pre-commit Skipped, or lint-staged Failing
How to fix Git hooks not executing — Husky v9 setup, hook file permissions, lint-staged configuration, pre-commit Python tool, lefthook, and bypassing hooks in CI.
Fix: Turborepo Not Working — Cache Never Hits, Pipeline Not Running, or Workspace Task Fails
How to fix Turborepo issues — turbo.json pipeline configuration, cache keys, remote caching setup, workspace filtering, and common monorepo task ordering mistakes.