📝 Description
When executing gh api commands, cli attempts to resolve authentication tokens for the target host via the configured credential store (such as the system keyring, environment variables, or config files). If credential retrieval from the system keyring fails due to an operational or system error (e.g., locked keychain, missing D-Bus session, OS permission denied, corrupted secret store), the error is swallowed and treated as if no credentials exist.
Consequently, gh api silently proceeds with an unauthenticated HTTP request. This results in misleading downstream API errors—such as HTTP 404 Not Found for private resources or HTTP 403 API rate limit exceeded—masking the underlying keyring issue and complicating debugging.
🎯 Acceptance Criteria
🛠️ Technical Specifications & Context
- Repository / Tech Stack: Go (
condoraltidoi32/cli).
- Relevant Packages:
pkg/cmd/api/api.go: API command execution logic and HTTP client instantiation.
pkg/cmd/factory/: Factory methods constructing the authenticated http.Client and HttpClientFunc.
internal/config/: Configuration reader and auth token retrieval mechanisms (AuthToken, Authentication).
pkg/authtoken/ / Keyring implementation (e.g., wrapper around zalando/go-keyring or platform secret services).
- Implementation Strategy:
- Inspect the keyring token retrieval function (e.g.,
TokenFromKeyring or Keyring.Get). Ensure it returns wrapped errors conforming to errors.Is(err, keyring.ErrNotFound) when a secret is absent vs when the keyring daemon fails.
- In the token resolution pipeline (e.g.,
AuthTokenForHost / AuthToken), do not discard operational errors from the keyring. If an error other than "not found" is encountered, halt execution and propagate the error.
- Ensure
pkg/cmd/api handles this propagated error by surfacing it before constructing or executing the HTTP request.
🧪 Verification & Testing
- Unit Tests:
- Add unit tests in the auth/config package verifying that
ErrNotFound proceeds through the resolution chain, while generic/operational errors (errors.New("dbus: connection closed"), errSecAuthFailed) halt execution and return the error.
- Add tests for
gh api verifying that an operational keyring error terminates the command with the proper exit code and error output.
- Manual Verification:
- Configure
gh to store credentials in the system keyring.
- Simulate a keyring failure (e.g., in Linux, run
unset DBUS_SESSION_BUS_ADDRESS; gh api user or lock the login keychain on macOS).
- Verify that
gh api repos/<private-repo> outputs a keyring error and halts instead of performing an unauthenticated request that returns HTTP 404.
- Verify that normal authentication still functions properly when the keyring is accessible or when
GH_TOKEN is supplied.

📝 Description
When executing
gh apicommands,cliattempts to resolve authentication tokens for the target host via the configured credential store (such as the system keyring, environment variables, or config files). If credential retrieval from the system keyring fails due to an operational or system error (e.g., locked keychain, missing D-Bus session, OS permission denied, corrupted secret store), the error is swallowed and treated as if no credentials exist.Consequently,
gh apisilently proceeds with an unauthenticated HTTP request. This results in misleading downstream API errors—such asHTTP 404 Not Foundfor private resources orHTTP 403 API rate limit exceeded—masking the underlying keyring issue and complicating debugging.🎯 Acceptance Criteria
ErrNotFound) and an operational keyring failure (e.g., D-Bus disconnected, keychain locked, access denied).gh api, the command must abort immediately and return a non-zero exit code.stderrexplaining that keyring access failed, providing the underlying OS/keyring error message and troubleshooting advice (e.g., verifying keyring status or settingGH_TOKEN).GH_TOKEN/GITHUB_TOKENenvironment variables -> keyring -> hosts config file) remains intact when a provider is simply not set/found.🛠️ Technical Specifications & Context
condoraltidoi32/cli).pkg/cmd/api/api.go: API command execution logic and HTTP client instantiation.pkg/cmd/factory/: Factory methods constructing the authenticatedhttp.ClientandHttpClientFunc.internal/config/: Configuration reader and auth token retrieval mechanisms (AuthToken,Authentication).pkg/authtoken// Keyring implementation (e.g., wrapper aroundzalando/go-keyringor platform secret services).TokenFromKeyringorKeyring.Get). Ensure it returns wrapped errors conforming toerrors.Is(err, keyring.ErrNotFound)when a secret is absent vs when the keyring daemon fails.AuthTokenForHost/AuthToken), do not discard operational errors from the keyring. If an error other than "not found" is encountered, halt execution and propagate the error.pkg/cmd/apihandles this propagated error by surfacing it before constructing or executing the HTTP request.🧪 Verification & Testing
ErrNotFoundproceeds through the resolution chain, while generic/operational errors (errors.New("dbus: connection closed"),errSecAuthFailed) halt execution and return the error.gh apiverifying that an operational keyring error terminates the command with the proper exit code and error output.ghto store credentials in the system keyring.unset DBUS_SESSION_BUS_ADDRESS; gh api useror lock the login keychain on macOS).gh api repos/<private-repo>outputs a keyring error and halts instead of performing an unauthenticated request that returnsHTTP 404.GH_TOKENis supplied.