Fix project scope errors during issue creation by maxbeizer · Pull Request #14035 · cli/cli · GitHub
Skip to content

Fix project scope errors during issue creation - #14035

Draft
maxbeizer wants to merge 10 commits into
cli:trunkfrom
maxbeizer:maxbeizer-fix-project-scope-error
Draft

maxbeizer wants to merge 10 commits into
cli:trunkfrom
maxbeizer:maxbeizer-fix-project-scope-error

Conversation

@maxbeizer

@maxbeizer maxbeizer commented Aug 1, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #8798

Surface missing ProjectV2 read:project authorization failures when an issue or pull request is explicitly created with --project. Previously, an inaccessible requested ProjectV2 was reported as not found.

  • Preserve graceful ProjectV2 degradation for optional metadata, including gh issue view and gh pr view
  • Continue resolving matching classic projects even when ProjectV2 discovery lacks read:project
  • Keep the existing non-interactive gh project missing-scope output unchanged
  • Add regression coverage for issue creation, pull request creation, and deferred project-title resolution

Local demonstration

Fixture-backed checks

From this PR branch, run the focused tests without changing credentials or creating GitHub content:

go test ./pkg/cmd/issue/create -run '^TestIssueCreate_projectMissingReadScope$'
go test ./pkg/cmd/pr/create -run '^Test_createRun/nontty_project_missing_read_scope$'
go test ./api -run '^(TestProjectsV2IgnorableError_missingProjectScope|TestRepoMetadataResultProjectsTitlesToIDsWithMissingProjectsV2Scopes)$'

These exercise an INSUFFICIENT_SCOPES response requiring read:project. They show that explicit issue/PR creation returns actionable scope guidance, while optional ProjectV2 lookup remains ignorable and classic-project resolution still succeeds.

Live comparison with trunk

Use a disposable repository and a token that can access that repository but deliberately lacks read:project. Choose the title of a ProjectV2 that is attached to the repository. Both commands stop during metadata resolution, before creating an issue.

# From this PR checkout
make

# Create a sibling baseline checkout once.
git worktree add ../cli-8798-trunk trunk
(
  cd ../cli-8798-trunk
  make
)

export GH_TOKEN='token-without-read-project'
export DEMO_REPO='OWNER/disposable-repo'
export DEMO_PROJECT='Attached ProjectV2 title'

# Current behavior
../cli-8798-trunk/bin/gh issue create \
  --repo "$DEMO_REPO" \
  --title 'scope demo - baseline' \
  --body 'should not be created' \
  --project "$DEMO_PROJECT"

# Proposed behavior
./bin/gh issue create \
  --repo "$DEMO_REPO" \
  --title 'scope demo - proposed fix' \
  --body 'should not be created' \
  --project "$DEMO_PROJECT"

Captured locally against cli/cli with a token that lacks read:project:

# trunk
could not add to project: 'roadmap' not found

# this PR
error: your authentication token is missing required scopes [read:project]
Update your authentication token to include: read:project

The same comparison applies to gh pr create --project, but the fixture-backed PR test above is preferred because it cannot create a pull request.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@github-actions github-actions Bot added external pull request originating outside of the CLI core team needs-triage needs to be reviewed labels Aug 1, 2026
maxbeizer and others added 5 commits August 1, 2026 11:18
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings August 24, 2026 18:38

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

Improves project-scope error reporting during issue and pull request creation while preserving optional metadata behavior.

Changes:

  • Parses structured GraphQL missing-scope errors.
  • Propagates deferred ProjectV2 scope failures during project resolution.
  • Adds API and command regression tests.
Show a summary per file
File Description
api/client.go Adds missing-scope parsing and error formatting.
api/client_test.go Tests scope extraction and formatting.
api/queries_projects_v2.go Recognizes structured ProjectV2 scope errors.
api/queries_projects_v2_test.go Tests ignorable missing-scope errors.
api/queries_repo.go Carries scope failures through project resolution.
api/queries_repo_test.go Tests classic and inaccessible project resolution.
pkg/cmd/issue/create/create_test.go Covers issue creation without project scope.
pkg/cmd/pr/create/create_test.go Covers pull request creation without project scope.
pkg/cmd/pr/shared/params.go Surfaces missing-scope errors during metadata resolution.

Review details

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Suppressed comments (1)

api/client_test.go:72

  • 🛑 Requirement: Use require for these error assertions. AGENTS.md:110-118 requires error checks to stop the test immediately, preventing later assertions from running against an invalid setup.
	assert.EqualError(t, GraphQLMissingScopesError(err), "error: your authentication token is missing required scopes [read:discussion read:project]\nUpdate your authentication token to include: read:discussion,read:project")
	assert.Empty(t, GraphQLMissingScopes(errors.New("not a GraphQL error")))
	assert.NoError(t, GraphQLMissingScopesError(errors.New("not a GraphQL error")))
  • Files reviewed: 9/9 changed files
  • Comments generated: 4
  • Review effort level: Balanced

Comment on lines +118 to +120
var missingScopesErr api.MissingScopesError
if errors.As(err, &missingScopesErr) {
return missingScopesErr
Comment thread api/client.go Outdated
Comment on lines +74 to +79
m := requiredScopesRE.FindStringSubmatch(graphQLError.Message)
if m == nil {
continue
}
for _, scope := range strings.Split(m[1], ",") {
missing[strings.Trim(scope, "' ")] = struct{}{}
Comment thread api/client_test.go
Comment on lines +49 to +50
reg := &httpmock.Registry{}
client := newTestClient(reg)
Comment on lines +346 to +347

This branch has not been deployed

No deployments
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.

gh issue create with project fails when permissions haven't been assigned

2 participants