Add "Resource not accessible" to ProjectsV2IgnorableError#13281
Merged
williammartin merged 1 commit intoApr 28, 2026
Conversation
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 cli#13280 Co-authored-by: Copilot <[email protected]>
Contributor
There was a problem hiding this comment.
Pull request overview
Updates the ProjectsV2 permission error handling so commands gracefully omit project data (instead of failing) when the token lacks Projects access and GitHub returns “Resource not accessible by …” GraphQL errors.
Changes:
- Add a new ignorable error pattern for “Resource not accessible by …” to
ProjectsV2IgnorableError. - Update function documentation to include authorization errors in the ignorable set.
- Add unit tests covering both “integration” and “personal access token” variants, including a “GraphQL: … (path)” contextual form.
Show a summary per file
| File | Description |
|---|---|
| api/queries_projects_v2.go | Adds a new ignorable error constant and includes it in ProjectsV2IgnorableError matching. |
| api/queries_projects_v2_test.go | Adds test cases to ensure the new error variants are treated as ignorable. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 2/2 changed files
- Comments generated: 0
williammartin
approved these changes
Apr 28, 2026
Member
williammartin
left a comment
There was a problem hiding this comment.
Using a PAT that only has the following permissions:
And targeting a PR that is attached to a project.
Before
➜ GH_TOKEN=<PAT> GH_DEBUG=api gh pr view https://github.com/williammartin-test-org/test-repo/pull/32 --json projectItems
⣾* Request at 2026-04-28 12:14:52.494868 +0200 CEST m=+0.062683043
* Request to https://api.github.com/graphql
> POST /graphql HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Length: 284
> Content-Type: application/json; charset=utf-8
> Graphql-Features: merge_queue
> Time-Zone: Europe/Amsterdam
> User-Agent: GitHub CLI 2.91.0
> X-Github-Api-Version: 2022-11-28
GraphQL query:
query PullRequestByNumber($owner: String!, $repo: String!, $pr_number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr_number) {id,number}
}
}
GraphQL variables: {"owner":"williammartin-test-org","pr_number":32,"repo":"test-repo"}
⡿< HTTP/2.0 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 28 Apr 2026 10:14:52 GMT
< Github-Authentication-Token-Expiration: 2026-05-28 09:55:55 UTC
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: FE40:322B12:179BD2D2:15D32281:69F0889C
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4909
< X-Ratelimit-Reset: 1777371636
< X-Ratelimit-Resource: graphql
< X-Ratelimit-Used: 91
< X-Xss-Protection: 0
{
"data": {
"repository": {
"pullRequest": {
"id": "PR_kwDONc_ZUs6SpjBI",
"number": 32
}
}
}
}
* Request took 533.774417ms
* Request at 2026-04-28 12:14:53.030466 +0200 CEST m=+0.598277251
* Request to https://api.github.com/graphql
> POST /graphql HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Length: 483
> Content-Type: application/json
> Graphql-Features: merge_queue
> Time-Zone: Europe/Amsterdam
> User-Agent: GitHub CLI 2.91.0
> X-Github-Api-Version: 2022-11-28
GraphQL query:
query PullRequestProjectItems($endCursor:String$name:String!$number:Int!$owner:String!){repository(owner: $owner, name: $name){pullRequest(number: $number){projectItems(first: 100, after: $endCursor){totalCount,nodes{id,project{id,title},status:fieldValueByName(name: "Status"){... on ProjectV2ItemFieldSingleSelectValue{optionId,name}}},pageInfo{hasNextPage,endCursor}}}}}
GraphQL variables: {"endCursor":null,"name":"test-repo","number":32,"owner":"williammartin-test-org"}
⣾< HTTP/2.0 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 28 Apr 2026 10:14:53 GMT
< Github-Authentication-Token-Expiration: 2026-05-28 09:55:55 UTC
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: FE40:322B12:179BD79C:15D326FC:69F0889D
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4908
< X-Ratelimit-Reset: 1777371636
< X-Ratelimit-Resource: graphql
< X-Ratelimit-Used: 92
< X-Xss-Protection: 0
{
"data": {
"repository": {
"pullRequest": {
"projectItems": {
"totalCount": 1,
"nodes": [
null
],
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
}
}
}
}
},
"errors": [
{
"type": "FORBIDDEN",
"path": [
"repository",
"pullRequest",
"projectItems",
"nodes",
0
],
"extensions": {
"saml_failure": false
},
"locations": [
{
"line": 1,
"column": 212
}
],
"message": "Resource not accessible by personal access token"
}
]
}
* Request took 458.116292ms
GraphQL: Resource not accessible by personal access token (repository.pullRequest.projectItems.nodes.0)
After
➜ GH_DEBUG=api ./bin/gh pr view https://github.com/williammartin-test-org/test-repo/pull/32 --json projectItems | cat
* Request at 2026-04-28 12:15:25.251331 +0200 CEST m=+0.019348668
* Request to https://api.github.com/graphql
> POST /graphql HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Length: 284
> Content-Type: application/json; charset=utf-8
> Graphql-Features: merge_queue
> Time-Zone: Europe/Amsterdam
> User-Agent: GitHub CLI v2.91.0-29-gdde46dc42
> X-Github-Api-Version: 2022-11-28
GraphQL query:
query PullRequestByNumber($owner: String!, $repo: String!, $pr_number: Int!) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $pr_number) {id,number}
}
}
GraphQL variables: {"owner":"williammartin-test-org","pr_number":32,"repo":"test-repo"}
< HTTP/2.0 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 28 Apr 2026 10:15:25 GMT
< Github-Authentication-Token-Expiration: 2026-05-28 09:55:55 UTC
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: FE49:32EE82:17A13FD3:15D98F6B:69F088BD
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4905
< X-Ratelimit-Reset: 1777371636
< X-Ratelimit-Resource: graphql
< X-Ratelimit-Used: 95
< X-Xss-Protection: 0
{
"data": {
"repository": {
"pullRequest": {
"id": "PR_kwDONc_ZUs6SpjBI",
"number": 32
}
}
}
}
* Request took 496.291542ms
* Request at 2026-04-28 12:15:25.750846 +0200 CEST m=+0.518859585
* Request to https://api.github.com/graphql
> POST /graphql HTTP/1.1
> Host: api.github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token ████████████████████
> Content-Length: 483
> Content-Type: application/json
> Graphql-Features: merge_queue
> Time-Zone: Europe/Amsterdam
> User-Agent: GitHub CLI v2.91.0-29-gdde46dc42
> X-Github-Api-Version: 2022-11-28
GraphQL query:
query PullRequestProjectItems($endCursor:String$name:String!$number:Int!$owner:String!){repository(owner: $owner, name: $name){pullRequest(number: $number){projectItems(first: 100, after: $endCursor){totalCount,nodes{id,project{id,title},status:fieldValueByName(name: "Status"){... on ProjectV2ItemFieldSingleSelectValue{optionId,name}}},pageInfo{hasNextPage,endCursor}}}}}
GraphQL variables: {"endCursor":null,"name":"test-repo","number":32,"owner":"williammartin-test-org"}
< HTTP/2.0 200 OK
< Access-Control-Allow-Origin: *
< Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset
< Content-Security-Policy: default-src 'none'
< Content-Type: application/json; charset=utf-8
< Date: Tue, 28 Apr 2026 10:15:26 GMT
< Github-Authentication-Token-Expiration: 2026-05-28 09:55:55 UTC
< Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin
< Server: github.com
< Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
< Vary: Accept-Encoding, Accept, X-Requested-With
< X-Content-Type-Options: nosniff
< X-Frame-Options: deny
< X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json
< X-Github-Request-Id: FE49:32EE82:17A144F2:15D993C4:69F088BD
< X-Ratelimit-Limit: 5000
< X-Ratelimit-Remaining: 4904
< X-Ratelimit-Reset: 1777371636
< X-Ratelimit-Resource: graphql
< X-Ratelimit-Used: 96
< X-Xss-Protection: 0
{
"data": {
"repository": {
"pullRequest": {
"projectItems": {
"totalCount": 1,
"nodes": [
null
],
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
}
}
}
}
},
"errors": [
{
"type": "FORBIDDEN",
"path": [
"repository",
"pullRequest",
"projectItems",
"nodes",
0
],
"extensions": {
"saml_failure": false
},
"locations": [
{
"line": 1,
"column": 212
}
],
"message": "Resource not accessible by personal access token"
}
]
}
* Request took 468.88825ms
{"projectItems":[]}
Notes
I had to only request --projectItems because statusRollupChecks is fetched by default on PRs and you can't get that with a user created FGPAT.
tmeijn
pushed a commit
to tmeijn/dotfiles
that referenced
this pull request
May 8, 2026
This MR contains the following updates: | Package | Update | Change | |---|---|---| | [cli/cli](https://github.com/cli/cli) | minor | `v2.90.0` → `v2.92.0` | MR created with the help of [el-capitano/tools/renovate-bot](https://gitlab.com/el-capitano/tools/renovate-bot). **Proposed changes to behavior should be submitted there as MRs.** --- ### Release Notes <details> <summary>cli/cli (cli/cli)</summary> ### [`v2.92.0`](https://github.com/cli/cli/releases/tag/v2.92.0): GitHub CLI 2.92.0 [Compare Source](cli/cli@v2.91.0...v2.92.0) #### Support GitHub Enterprise Cloud (GHEC) in `skill` commandset Now `gh skill` subcommands (`install`, `preview`, `publish`, `search`, `update`) are able to work with [GHEC](https://docs.github.com/en/enterprise-cloud@latest/admin/overview/about-github-enterprise-cloud) hosts with data residency. #### Add `--allow-hidden-dirs` flag to `skill preview` Following the addition of `--allow-hidden-dirs` to `skill install` in the previous release, now the flag is also supported in `skill preview`, allowing users to preview skills located in hidden (dot-prefixed) directories such as `.claude/skills/`, `.agents/skills/`, and `.github/skills/`. #### What's Changed ##### ✨ Features - feat(skills): add --allow-hidden-dirs flag to preview command by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13265](cli/cli#13265) - feat(skills): support GHEC with data residency hosts by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13264](cli/cli#13264) ##### 🐛 Fixes - Fix SetSampleRate not updating sample\_rate dimension by [@​williammartin](https://github.com/williammartin) in [#​13259](cli/cli#13259) - Fix log terminal injection by [@​williammartin](https://github.com/williammartin) in [#​13272](cli/cli#13272) - Add "Resource not accessible" to ProjectsV2IgnorableError by [@​maxbeizer](https://github.com/maxbeizer) in [#​13281](cli/cli#13281) ##### 📚 Docs & Chores - fix: using variable interpolation \`${{ in deployment.yml... by [@​orbisai0security](https://github.com/orbisai0security) in [#​13258](cli/cli#13258) - docs: correct typo in Linux Homebrew copy by [@​cassidyjames](https://github.com/cassidyjames) in [#​13273](cli/cli#13273) - Install skills flat by Name, not namespaced InstallName by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13266](cli/cli#13266) - chore: fix zsh completion on debian by [@​babakks](https://github.com/babakks) in [#​13274](cli/cli#13274) - Add trust disclaimer to extension help text by [@​travellertales](https://github.com/travellertales) in [#​13296](cli/cli#13296) - Bump Go to 1.26.2 by [@​github-actions](https://github.com/github-actions)\[bot] in [#​13301](cli/cli#13301) #####Dependencies - chore(deps): bump github.com/mattn/go-isatty from 0.0.20 to 0.0.21 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13161](cli/cli#13161) - chore(deps): bump github.com/google/go-containerregistry from 0.21.4 to 0.21.5 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13162](cli/cli#13162) - chore(deps): bump charm.land/lipgloss/v2 from 2.0.2 to 2.0.3 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13163](cli/cli#13163) - chore(deps): bump charm.land/bubbletea/v2 from 2.0.2 to 2.0.6 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13206](cli/cli#13206) - chore(deps): bump github.com/gdamore/tcell/v2 from 2.13.8 to 2.13.9 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13241](cli/cli#13241) - chore(deps): bump github.com/mattn/go-isatty from 0.0.21 to 0.0.22 by [@​dependabot](https://github.com/dependabot)\[bot] in [#​13298](cli/cli#13298) #### New Contributors - [@​orbisai0security](https://github.com/orbisai0security) made their first contribution in [#​13258](cli/cli#13258) - [@​cassidyjames](https://github.com/cassidyjames) made their first contribution in [#​13273](cli/cli#13273) - [@​travellertales](https://github.com/travellertales) made their first contribution in [#​13296](cli/cli#13296) **Full Changelog**: <cli/cli@v2.91.0...v2.92.0> ### [`v2.91.0`](https://github.com/cli/cli/releases/tag/v2.91.0): GitHub CLI 2.91.0 [Compare Source](cli/cli@v2.90.0...v2.91.0) #### GitHub CLI now collects pseudonymous telemetry To better understand how features are used in practice, especially as agentic adoption grows, GitHub CLI now sends pseudonymous telemetry. See [Telemetry](https://cli.github.com/telemetry) for more details on what's collected, why, and how to opt out. #### Support more agents in `gh skill` Thanks to community feedback, `gh` now supports a large number of agent hosts. Run `gh skill install --help` for the list of available agents. #### Improve skill discovery `gh skill install` now adds the `--allow-hidden-dirs` flag to support discovering skills in hidden (dot-prefixed) directories such as `.claude/skills/`, `.agents/skills/`, and `.github/skills/`. #### Detect skills re-published from other sources GitHut CLI now detects if the skill to be installed is re-published from an upstream source and offers the option to install it from there. The `--upstream` flag is also added for non-interactive use cases. #### What's Changed ##### ✨ Features - Add support for installation in multiple agent hosts in `gh skills install` by [@​tommaso-moro](https://github.com/tommaso-moro) in [#​13209](cli/cli#13209) - Add --allow-hidden-dirs flag to gh skill install by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13213](cli/cli#13213) - Make skill discovery less strict: support nested `skills/` directories by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13235](cli/cli#13235) - feat(skills): detect re-published skills and offer upstream install by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13236](cli/cli#13236) ##### 🐛 Fixes - Fix `skills publish --fix` to not publish by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13237](cli/cli#13237) - fix(skills): match skills by install name in preview command by [@​SamMorrowDrums](https://github.com/SamMorrowDrums) in [#​13249](cli/cli#13249) ##### 📚 Docs & Chores - Remove misleading text by [@​tommaso-moro](https://github.com/tommaso-moro) in [#​13203](cli/cli#13203) - Add sampled command telemetry by [@​williammartin](https://github.com/williammartin) in [#​13191](cli/cli#13191) - Do not send telemetry for aliases by [@​williammartin](https://github.com/williammartin) in [#​13192](cli/cli#13192) - Add skills specific telemetry by [@​williammartin](https://github.com/williammartin) in [#​13204](cli/cli#13204) - Record CI context in telemetry by [@​williammartin](https://github.com/williammartin) in [#​13210](cli/cli#13210) - Record official extension telemetry by [@​williammartin](https://github.com/williammartin) in [#​13205](cli/cli#13205) - Add telemetry command by [@​williammartin](https://github.com/williammartin) in [#​13253](cli/cli#13253) - Log when there is no telemetry by [@​williammartin](https://github.com/williammartin) in [#​13255](cli/cli#13255) - docs(skills): add gh and gh-skill agent skills by [@​BagToad](https://github.com/BagToad) in [#​13244](cli/cli#13244) - Enable telemetry without env var by [@​williammartin](https://github.com/williammartin) in [#​13254](cli/cli#13254) **Full Changelog**: <cli/cli@v2.90.0...v2.91.0> </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever MR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this MR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this MR, check this box --- This MR has been generated by [Mend Renovate](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My4xNjkuNCIsInVwZGF0ZWRJblZlciI6IjQzLjE2OS40IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6WyJSZW5vdmF0ZSBCb3QiLCJhdXRvbWF0aW9uOmJvdC1hdXRob3JlZCIsImRlcGVuZGVuY3ktdHlwZTo6bWlub3IiXX0=-->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When a token (GitHub App, fine-grained PAT, or
GITHUB_TOKEN) lacks theprojectpermission, queryingprojectItemson a PR or issue fails with"Resource not accessible by integration"or"Resource not accessible by personal access token".ProjectsV2IgnorableErrordid not match these errors, causing commands likepr view,pr edit, andissue viewto fail entirely instead of gracefully omitting project data.Changes
errorProjectsV2ResourceNotAccessibleconstant ("Resource not accessible by") toapi/queries_projects_v2.goProjectsV2IgnorableErrorcheck — the"by"prefix covers all three authorizer variants: "integration", "personal access token", and "this actor"This is safe because
ProjectsV2IgnorableErroris only called in project-specific code paths (PR finder, issue lookup, repo metadata).Closes #13280
Related: #6274, #8784