Describe the bug
When the configured SDK auth token (--auth-token-env / COPILOT_SDK_AUTH_TOKEN) hits any non-200 response at the validation step (GET /copilot_internal/user), the auth bootstrap silently fails. With --no-auto-login set (typical for headless SDK use), no other auth method runs, the Session is created without authentication, and the first model-touching operation surfaces as the misleading:
Execution failed: Error: Session was not created with authentication info or custom provider
The most common trigger in real workloads is GitHub's standard 5000 req/hr REST quota being exhausted on a service-account PAT shared across multiple consumers. When that bucket is empty, /copilot_internal/user returns 403 "API rate limit exceeded for user ID …". There is no retry on 403/429 at the auth-validation step, no surfacing of the underlying reason to the SDK caller, and no Retry-After honoring.
Confirmed reproducible against @github/copilot-sdk 0.3.0 with bundled CLI 1.0.36-0, and behavior is unchanged through CLI 1.0.47.
Reproduction
- Take any GitHub user PAT with Copilot access.
- Burn through its 5000 req/hr REST quota (easy via parallel curls or by running enough SDK sessions back-to-back).
- With quota exhausted, spawn a Copilot SDK session in headless mode using that PAT via
--auth-token-env/COPILOT_SDK_AUTH_TOKEN and --no-auto-login:
from copilot.client import CopilotClient, SubprocessConfig
from copilot.session import PermissionHandler
client = CopilotClient(SubprocessConfig(github_token=PAT, log_level="info"))
await client.start()
session = await client.create_session(
on_permission_request=PermissionHandler.approve_all,
model="claude-opus-4.6",
system_message={"mode": "replace", "content": "hi"},
)
await session.send("ping") # raises with the misleading "Session was not created…" error
- Direct probe with the same token to confirm the underlying cause:
GET https://api.github.com/rate_limit
Authorization: Bearer <PAT>
→ 200, {rate: {limit: 5000, used: 7912, remaining: 0, reset: ...}}
Evidence
~/.copilot/logs/process-*.log shows the swallowed error:
[ERROR] Failed to validate SDK token (403): API rate limit exceeded for user ID <REDACTED>. ...
But the only thing surfaced to the SDK caller is the eventual "Session was not created with authentication info or custom provider", which is not actionable — the user has no way from the SDK-side error to know it was actually a transient REST quota hit.
Three things compound to make this confusing
- Auth validation only retries HTTP/2 transport errors. A 403 / 429 / 5xx throws immediately on the first attempt, no backoff, no
Retry-After parsing.
- The validation failure is logged to the log file but not propagated through the SDK boundary. Callers using the Python SDK (and presumably others) get no signal at
client.start() / create_session() that auth bootstrap failed.
- The eventual "Session was not created…" error is generic. It surfaces later when the session tries to do its first model-touching operation, with no hint of the real upstream reason.
Suggested fixes
- Differentiate 429 / 403-with-
x-ratelimit-remaining: 0 from real auth failures at the validation step. Either retry with respect to x-ratelimit-reset, or surface a typed RateLimitedError through the SDK boundary.
- Surface auth-bootstrap failures through the SDK API. Today they only land in the log file; the caller has no way to know.
- Improve the user-facing error message when the session ends up unauthenticated due to a known prior failure: include the upstream status / reason instead of the generic "Session was not created with authentication info or custom provider".
Affected version
GitHub Copilot CLI 1.0.36-0 (bundled with @github/copilot-sdk 0.3.0) through 1.0.47. Behavior reproduces identically across this range.
Related
Describe the bug
When the configured SDK auth token (
--auth-token-env/COPILOT_SDK_AUTH_TOKEN) hits any non-200 response at the validation step (GET /copilot_internal/user), the auth bootstrap silently fails. With--no-auto-loginset (typical for headless SDK use), no other auth method runs, the Session is created without authentication, and the first model-touching operation surfaces as the misleading:The most common trigger in real workloads is GitHub's standard 5000 req/hr REST quota being exhausted on a service-account PAT shared across multiple consumers. When that bucket is empty,
/copilot_internal/userreturns 403"API rate limit exceeded for user ID …". There is no retry on 403/429 at the auth-validation step, no surfacing of the underlying reason to the SDK caller, and noRetry-Afterhonoring.Confirmed reproducible against
@github/copilot-sdk0.3.0 with bundled CLI 1.0.36-0, and behavior is unchanged through CLI 1.0.47.Reproduction
--auth-token-env/COPILOT_SDK_AUTH_TOKENand--no-auto-login:Evidence
~/.copilot/logs/process-*.logshows the swallowed error:But the only thing surfaced to the SDK caller is the eventual "Session was not created with authentication info or custom provider", which is not actionable — the user has no way from the SDK-side error to know it was actually a transient REST quota hit.
Three things compound to make this confusing
Retry-Afterparsing.client.start()/create_session()that auth bootstrap failed.Suggested fixes
x-ratelimit-remaining: 0from real auth failures at the validation step. Either retry with respect tox-ratelimit-reset, or surface a typedRateLimitedErrorthrough the SDK boundary.Affected version
GitHub Copilot CLI 1.0.36-0 (bundled with
@github/copilot-sdk0.3.0) through 1.0.47. Behavior reproduces identically across this range.Related