Skip to content

fix: clarify scope error while creating issues for projects#12596

Merged
BagToad merged 3 commits intocli:trunkfrom
elijahthis:fix/clarify-scope-error
Mar 2, 2026
Merged

fix: clarify scope error while creating issues for projects#12596
BagToad merged 3 commits intocli:trunkfrom
elijahthis:fix/clarify-scope-error

Conversation

@elijahthis
Copy link
Contributor

@elijahthis elijahthis commented Feb 1, 2026

Summary

Enhanced GraphQL error handling to provide more user-friendly and actionable messages when a token lacks the necessary permissions. Instead of a verbose technical trace, users now receive a concise list of missing scopes and a direct command to resolve the issue via gh auth refresh.

Changes

  • Modified handleResponse to intercept GraphQL errors and check for INSUFFICIENT_SCOPES types.
  • Implemented GenerateScopeErrorForGQL to extract specific required scopes from the API response message.
  • Added requiredScopesFromServerMessage using regex to parse scope requirements (e.g., project, repo) from the server's text.

Note

I basically replicated the logic being used for queries (handleError found in pkg/cmd/project/shared/queries/queries.go)
image

Example

Before (Raw GraphQL Trace):

GraphQL: Your token has not been granted the required scopes to execute this query. The 'addProjectV2ItemById' field requires one of the following scopes: ['project'], but your token has only been granted the: ['gist', 'read:org', 'read:project', 'repo', 'workflow'] scopes. Please modify your token's scopes at: https://github.com/settings/tokens.

Now (Clean CLI Error):

error: your authentication token is missing required scopes [project]
To request it, run:  gh auth refresh -s project

Test plan

  • Added test cases for newly-created functions
  • All existing tests pass

Fixes #12585

@elijahthis elijahthis requested a review from a team as a code owner February 1, 2026 22:34
@elijahthis elijahthis requested a review from babakks February 1, 2026 22:34
@cliAutomation cliAutomation added the external pull request originating outside of the CLI core team label Feb 1, 2026
@BagToad
Copy link
Member

BagToad commented Feb 3, 2026

Hey @elijahthis, thank you for the PR. It looks like there are some issues with the tests. Could you have a look at those and @ mention me when it's ready for review? 🙏

@elijahthis
Copy link
Contributor Author

Hey @elijahthis, thank you for the PR. It looks like there are some issues with the tests. Could you have a look at those and @ mention me when it's ready for review? 🙏

On it!

@elijahthis
Copy link
Contributor Author

Hii @BagToad seems GitHub Actions was down when I pushed the last time. Just pushed an empty commit and checks all pass.

Ready for review !

@BagToad BagToad self-requested a review February 4, 2026 17:15
@elijahthis
Copy link
Contributor Author

Hi @BagToad
Any update on this?

@gcomneno
Copy link

Tested PR #12596 locally on Ubuntu 24.04 (linux/amd64) with Go 1.25.6.

Commands run:
gh pr checkout -R cli/cli 12596
go test ./...

Result:
All packages passed.

I also grepped the implementation: the missing-scope detection appears to rely on parsing the GraphQL error message text via requiredScopesFromServerMessage(...) (e.g. in api/client.go and pkg/cmd/project/shared/queries/queries.go), rather than deriving required scopes from a structured field/header.

This seems fine as a pragmatic fix, but it is potentially brittle if GitHub changes the wording. To reduce risk, it may be worth adding/keeping a regression test that uses the exact message shown in #12585 (including the addProjectV2ItemById case) to lock the behavior.

Copy link
Member

@BagToad BagToad left a comment

Choose a reason for hiding this comment

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

@elijahthis, apologies for the delay. The team has been busy.

Tested this locally and it works correctly for the exact error from #12585, multi-scope scenarios, and non-scope errors. Approving as-is. I've opened #12823 to track deduplicating the scope error handling between api/client.go and queries.go - I do think we should do this at some point or at least document why it's not possible or practical.

@elijahthis, if you want to take a stab at that cleanup I've opened that issue up for contributing.

@BagToad BagToad merged commit e725e38 into cli:trunk Mar 2, 2026
11 checks passed
@elijahthis
Copy link
Contributor Author

Thanks for the heads-up @BagToad ! Happy to try my hands at #12823 .

@camjac251
Copy link

camjac251 commented Mar 12, 2026

Hey @elijahthis, this PR appears to have introduced a regression that is now tracked in #12904.

The issue: GenerateScopeErrorForGQL() in api/client.go:184-186 rewrites INSUFFICIENT_SCOPES GraphQL errors inside handleResponse() before callers see the original error. This breaks ProjectsV2IgnorableError() (api/queries_projects_v2.go:328-339), which checks for the original API substring:

"field requires one of the following scopes: ['read:project']"

After rewriting, the error says:

"your authentication token is missing required scopes [read:project]"

The ignorable-error check no longer matches, so an optional projectItems query failure becomes fatal, breaking gh pr view, gh pr edit, etc. for any token without read:project (which was never required before).

Call chain: gh pr view/edit -> finder.Find() -> ProjectsV2ItemsForPullRequest() -> client.Query() -> handleResponse() rewrites error -> ProjectsV2IgnorableError() fails to match -> fatal error.

#12845 (cc @yuvrajangadsingh) further refactored this path but inherited the same issue.

Suggested fix: The simplest correct fix would be to move GenerateScopeErrorForGQL out of handleResponse() and into the specific callers that need fatal scope errors (e.g. gh issue create --project). The original behavior was correct: scope errors were non-fatal by default, and ProjectsV2IgnorableError could recognize and suppress them. Making all scope errors fatal at the lowest level, then expecting callers to un-fatalize them via brittle string matching, inverts that contract.

Alternatively, a typed ScopeError struct that ProjectsV2IgnorableError can check with errors.As would also work and be more future-proof.

@yuvrajangadsingh
Copy link
Contributor

@camjac251 good catch, yeah #12845 inherited this. opened #12913 to fix it, just removes the GenerateScopeErrorForGQL call from handleResponse so the original GraphQLError flows through to ProjectsV2IgnorableError. project commands still handle scope errors through their own handleError.

@williammartin
Copy link
Member

Hey @elijahthis, I've reverted this PR in #12915 because it unfortunately resulted in a pretty bad bug. Don't worry about it though, it was the result some nasty fragile code far away in the codebase that you never could have predicated, and was even hard to catch for us in review. I've reopened the original issue.

raajheshkannaa added a commit to raajheshkannaa/cli-1 that referenced this pull request Mar 14, 2026
When a GraphQL query fails with INSUFFICIENT_SCOPES, the GitHub API error
message tells users to visit token settings, which is unhelpful for OAuth
users. This adds a scopes suggestion to GraphQLError (matching the pattern
already used by HTTPError) that prints "gh auth refresh -s <scope>" after
the error.

Unlike the reverted PR cli#12596, this does NOT rewrite the original error
message. The suggestion is stored separately on GraphQLError and printed
by the top-level error handler. This preserves the original error text so
ProjectsV2IgnorableError can still match against it, avoiding the
regression that caused the revert.
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Confusing error message on scopes

7 participants