Add "Resource not accessible" to ProjectsV2IgnorableError

When a token (GitHub App, fine-grained PAT, or GITHUB_TOKEN) lacks the
project permission, querying projectItems on a PR or issue fails with
"Resource not accessible by integration" or "Resource not accessible by
personal access token". ProjectsV2IgnorableError did not match these
errors, causing commands like pr view, pr edit, and issue view to fail
entirely instead of gracefully omitting project data.

Add "Resource not accessible by" as an ignorable error prefix. This is
safe because ProjectsV2IgnorableError is only called in project-specific
code paths.

Closes #13280

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Max Beizer 2026-04-24 17:16:00 -05:00
parent ea7a2450cd
commit dde46dc424
No known key found for this signature in database
2 changed files with 29 additions and 11 deletions

View file

@ -9,12 +9,13 @@ import (
)
const (
errorProjectsV2ReadScope = "field requires one of the following scopes: ['read:project']"
errorProjectsV2UserField = "Field 'projectsV2' doesn't exist on type 'User'"
errorProjectsV2RepositoryField = "Field 'projectsV2' doesn't exist on type 'Repository'"
errorProjectsV2OrganizationField = "Field 'projectsV2' doesn't exist on type 'Organization'"
errorProjectsV2IssueField = "Field 'projectItems' doesn't exist on type 'Issue'"
errorProjectsV2PullRequestField = "Field 'projectItems' doesn't exist on type 'PullRequest'"
errorProjectsV2ReadScope = "field requires one of the following scopes: ['read:project']"
errorProjectsV2UserField = "Field 'projectsV2' doesn't exist on type 'User'"
errorProjectsV2RepositoryField = "Field 'projectsV2' doesn't exist on type 'Repository'"
errorProjectsV2OrganizationField = "Field 'projectsV2' doesn't exist on type 'Organization'"
errorProjectsV2IssueField = "Field 'projectItems' doesn't exist on type 'Issue'"
errorProjectsV2PullRequestField = "Field 'projectItems' doesn't exist on type 'PullRequest'"
errorProjectsV2ResourceNotAccessible = "Resource not accessible by"
)
type ProjectV2 struct {
@ -321,10 +322,11 @@ func CurrentUserProjectsV2(client *Client, hostname string) ([]ProjectV2, error)
}
// When querying ProjectsV2 fields we generally don't want to show the user
// scope errors and field does not exist errors. ProjectsV2IgnorableError
// checks against known error strings to see if an error can be safely ignored.
// Due to the fact that the GraphQLClient can return multiple types of errors
// this uses brittle string comparison to check against the known error strings.
// scope errors, field does not exist errors, or authorization errors.
// ProjectsV2IgnorableError checks against known error strings to see if an
// error can be safely ignored. Due to the fact that the GraphQLClient can
// return multiple types of errors this uses brittle string comparison to check
// against the known error strings.
func ProjectsV2IgnorableError(err error) bool {
msg := err.Error()
if strings.Contains(msg, errorProjectsV2ReadScope) ||
@ -332,7 +334,8 @@ func ProjectsV2IgnorableError(err error) bool {
strings.Contains(msg, errorProjectsV2RepositoryField) ||
strings.Contains(msg, errorProjectsV2OrganizationField) ||
strings.Contains(msg, errorProjectsV2IssueField) ||
strings.Contains(msg, errorProjectsV2PullRequestField) {
strings.Contains(msg, errorProjectsV2PullRequestField) ||
strings.Contains(msg, errorProjectsV2ResourceNotAccessible) {
return true
}
return false

View file

@ -317,6 +317,21 @@ func TestProjectsV2IgnorableError(t *testing.T) {
errMsg: "Field 'projectItems' doesn't exist on type 'PullRequest'",
expectOut: true,
},
{
name: "resource not accessible by integration",
errMsg: "Resource not accessible by integration",
expectOut: true,
},
{
name: "resource not accessible by personal access token",
errMsg: "Resource not accessible by personal access token",
expectOut: true,
},
{
name: "resource not accessible by integration with path context",
errMsg: "GraphQL: Resource not accessible by integration (repository.pullRequest.projectItems.nodes.0)",
expectOut: true,
},
{
name: "other error",
errMsg: "some other graphql error message",