Repository navigation
1.0.98: Copilot Enterprise account routed to api.business.githubcopilot.com — 401 on model catalog, 'Authentication failed' despite valid token #5165
Description
Environment
- Copilot CLI 1.0.98 (installed via official
gh.io/copilot-installscript, Linux x64, headless — no system keychain, token stored in plaintext~/.copilot/config.json) - Auth via
copilot login --device-codeon github.com (not a GHEC data-residency tenant,GH_HOSTunset) - Account shape: personal account whose GitHub Copilot access is provided by a GitHub Enterprise Cloud organization with a Copilot Enterprise seat (org Copilot management page shows "GitHub Copilot Enterprise", seat assigned and listed under "members with access to Copilot")
Symptom
Every copilot -p "<prompt>" invocation fails immediately:
Error: Authentication failed (Request ID: ...)
Your GitHub token may be invalid, expired, or lacking the required permissions.
CLI log (same run):
[ERROR] worker quit with fatal: Transport channel closed, when Client(OAuthChallenge { status_code: 401 ... })
[WARNING] MCP OAuth authorization failed; reporting the server as needing auth {"server":"github-mcp-server","error":"Browser-based OAuth required for https://api.business.githubcopilot.com/mcp/readonly"}
[ERROR] Error loading models: Error: 401 "Unauthorized"
The model-catalog fetch and the built-in github-mcp-server both target api.business.githubcopilot.com for this account.
The token is valid
The stored token returns 200 on GET https://api.github.com/user with the correct account, so "invalid/expired token" is not the cause.
Host matrix (same token, GET <host>/models)
| Host | Result |
|---|---|
https://api.business.githubcopilot.com/models |
401 Unauthorized (x-copilot-service-request-id: 717f9174-81b4-4f3d-a2bb-816f5b9e0d0b) |
https://api.enterprise.githubcopilot.com/models |
200 — full model catalog returned |
https://api.githubcopilot.com/models |
200 — full model catalog returned |
So the account is authorized on the enterprise (and generic) Copilot API hosts, but the CLI routes this Copilot Enterprise-seat account to the business host, where it is rejected with 401. The CLI appears to classify the account as Copilot Business rather than Enterprise when resolving the Copilot API base (authGetCopilotApiUrl).
Impact
CLI is completely unusable for Copilot Enterprise accounts with a valid seat: the first authenticated call (model catalog) 401s, before any prompt can run. The error message is misleading — it suggests a token problem, but the token is fine; only the target host is wrong.
Reproduction
- Have a personal account whose Copilot is provided by a GitHub Enterprise Cloud org with a Copilot Enterprise seat.
copilot login(device code flow).copilot -p "hi"→Error: Authentication failed.curl -H "Authorization: Bearer <stored token>" https://api.githubcopilot.com/models→ 200, while the CLI's business host → 401.
Related
copilot -pfails with 401 on GHEC data residency since 1.0.81-1 — prompt mode model-catalog fetch hitsapi.githubcopilot.cominstead of the tenant endpoint #4527 — prompt-mode model-catalog fetch hit the wrong host (fixed for GHEC data-residency tenants); same defect class for enterprise-routed accounts.- github-mcp-server: /mcp authenticate always fails on Copilot Enterprise — enterprise MCP host advertises a cross-origin resource identifier #4408 — enterprise-routed accounts resolve the Copilot API base to
api.enterprise.githubcopilot.com; for this account the CLI resolves it toapi.business.githubcopilot.cominstead, and that host 401s.
Activity
hermes-realeye commentedon Oct 16, 2026
Follow-up with a concrete root-cause finding from this environment (repro account still available):
The bad host is issued by the server, keyed by client version
The Copilot CLI fetches per-account endpoint info at startup, and the response includes
endpoints.apiandendpoints.telemetry. The same account, same cache key gets different endpoints depending on which CLI version made the request:copilot_plan/access_type_skuin responseendpoints.apiissuedhttps://api.business.githubcopilot.com/modelsand every model callhttps://api.business.githubcopilot.comhttps://api.enterprise.githubcopilot.comThe account is a Copilot Enterprise seat; its token is valid (GitHub API
GET /user200; same token returns 200 model catalogs on bothapi.enterprise.githubcopilot.comandapi.githubcopilot.com). So the 1.0.98+ clients are being told by the endpoint-info response to use a host that rejects their own token, while 1.0.97 clients are told to use the host that accepts it. This points at the endpoint-assignment logic (version-gated rollout of the new host mapping?) rather than at the CLI's own routing code or at org policy.Secondary trap: the endpoint response is cached
~/.cache/copilot/copilot-user-cache.json(marked "Disposable cache … safe to delete. Managed automatically") caches that response. A client that was previously run at 1.0.98+ keeps using the cached business endpoint even after being replaced by the 1.0.97 launcher, until the cache is cleared — so a downgrade alone does not help; the cache must be removed (or expired) first.Workaround that works on the user's own license
~/.cache/copilot/pkg/linux-x64/.~/.cache/copilot/copilot-user-cache.jsonandexp-cache.json.api.enterprise.githubcopilot.com.Note for maintainers:
copilot --versionprints the newest runtime present in thepkgdirectory, not the version actually executed — each launcher binary runs its own compiled version. This made version diagnosis confusing and may mislead users filing reports.Relevant issues: #4527, #4408. Happy to provide further details from this repro environment.