Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix auth status messaging for network failures - #12878

Closed
edwardwc wants to merge 1 commit into
cli:trunkfrom
edwardwc:fix/auth-status-network-errors
Closed

edwardwc wants to merge 1 commit into
cli:trunkfrom
edwardwc:fix/auth-status-network-errors

Conversation

@edwardwc

@edwardwc edwardwc commented Mar 9, 2026

Copy link
Copy Markdown

Summary

gh auth status currently reports that a token is invalid when the underlying auth check failed because the network request itself failed, for example in a sandboxed environment or during DNS resolution failures.

This change keeps the existing JSON output shape intact, but updates the human-readable status text to distinguish invalid credentials from transport-level verification failures for both stored tokens and environment tokens.

What Changed

  • classify auth check failures as invalid-auth, network, timeout, or unknown for display purposes
  • keep JSON state values unchanged as success, error, or timeout
  • only show re-authentication guidance for actual invalid-credential failures
  • add coverage for stored-token and env-token network failures, plus real invalid-credential cases

Verification

env GOCACHE=/tmp/go-build GOMODCACHE=/tmp/gomodcache go test ./pkg/cmd/auth/status -count=1

Copilot AI review requested due to automatic review settings March 9, 2026 01:31
@edwardwc
edwardwc requested a review from a team as a code owner March 9, 2026 01:31
@edwardwc
edwardwc requested a review from babakks March 9, 2026 01:31
@github-actions github-actions Bot added external pull request originating outside of the CLI core team needs-triage needs to be reviewed labels Mar 9, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Updates gh auth status to distinguish invalid credentials from network/verification failures in human-readable output while keeping the JSON schema unchanged.

Changes:

  • Add error classification (invalid_auth, network, unknown) and adjust error messaging/header text accordingly.
  • Extend tests to cover network failures and env-token invalid-token behavior, and update existing expectations for 401 “Bad credentials” cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
pkg/cmd/auth/status/status.go Adds auth error classification and updates human-readable error output based on failure kind.
pkg/cmd/auth/status/status_test.go Adds/updates test cases for network errors and invalid env tokens; adjusts expected outputs for 401 scenarios.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +139 to +145
reg.Register(httpmock.REST("GET", ""), func(req *http.Request) (*http.Response, error) {
return nil, &url.Error{
Op: "Get",
URL: "https://api.github.com/",
Err: &net.DNSError{Err: "no such host", Name: "api.github.com"},
}
})

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test stub is returning a *url.Error from the mocked RoundTripper. net/http typically wraps transport errors in *url.Error itself, so returning a url.Error here can lead to double-wrapping and a brittle, duplicated error string in wantErrOut. Consider returning the underlying error (e.g., *net.DNSError) and letting http.Client construct the url.Error so the message format is stable and closer to real behavior.

Copilot uses AI. Check for mistakes.
Comment on lines +458 to +462
errMsg := err.Error()
if strings.Contains(errMsg, "401 Unauthorized") || strings.Contains(errMsg, "Bad credentials") {
return authEntryStateError, authFailureKindInvalidAuth
}

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

classifyAuthError falls back to substring matching on err.Error() ("401 Unauthorized" / "Bad credentials") to detect invalid auth. This is brittle and can misclassify unrelated errors or break if upstream error formatting changes. Prefer classifying based on concrete error types / status codes (e.g., handle go-gh's HTTP error type if it differs from api.HTTPError, or extract the status code via a typed interface) and avoid relying on error string contents.

Suggested change
errMsg := err.Error()
if strings.Contains(errMsg, "401 Unauthorized") || strings.Contains(errMsg, "Bad credentials") {
return authEntryStateError, authFailureKindInvalidAuth
}

Copilot uses AI. Check for mistakes.
Comment on lines +160 to +166
reg.Register(httpmock.GraphQL(`query UserCurrent\b`), func(req *http.Request) (*http.Response, error) {
return nil, &url.Error{
Op: "Post",
URL: "https://api.github.com/graphql",
Err: &net.DNSError{Err: "no such host", Name: "api.github.com"},
}
})

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as the other network-error case: returning *url.Error from the mocked transport can cause net/http to wrap it again, producing a duplicated "Post ...: Post ..." error string that’s sensitive to implementation details. Returning the underlying *net.DNSError (and letting http.Client wrap) makes the expectation more stable.

Copilot uses AI. Check for mistakes.
Comment on lines +750 to +756
reg.Register(httpmock.REST("GET", ""), func(req *http.Request) (*http.Response, error) {
return nil, &url.Error{
Op: "Get",
URL: "https://api.github.com/",
Err: &net.DNSError{Err: "no such host", Name: "api.github.com"},
}
})

Copilot AI Mar 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This JSON-mode network error stub also returns *url.Error directly from the RoundTripper, which can lead to double-wrapped errors and brittle exact-string assertions. Consider returning the underlying error (e.g., *net.DNSError) and updating wantOut accordingly so the error string is less dependent on net/http internals.

Copilot uses AI. Check for mistakes.
@babakks

babakks commented Mar 9, 2026

Copy link
Copy Markdown
Member

Hi @edwardwc! 👋 This seems like a good idea, of course if there are valid use cases for it. So, as this needs more discussion on the rationale, I'm going to close the PR, as the PR is not yet in a reviewable stage.

Can you please create an issue, explaining the rationale/use case? Please also cover more about your specific use case/situation to help us and the community better understand the need for this.

@edwardwc

Copy link
Copy Markdown
Author

Opened the follow-up issue requested here: #12891\n\nIssue link: https://github.com/cli/cli/issues/12891\n\nIt documents the rationale, concrete sandbox/network failure use case, and the reproduction details behind this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external pull request originating outside of the CLI core team needs-triage needs to be reviewed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants