Skip to content

feat(coding-agents): Detect GitHub App 403 permission errors and return structured failure_type#108451

Merged
JoshFerge merged 5 commits intomasterfrom
jferg/copilot-403-backend
Feb 18, 2026
Merged

feat(coding-agents): Detect GitHub App 403 permission errors and return structured failure_type#108451
JoshFerge merged 5 commits intomasterfrom
jferg/copilot-403-backend

Conversation

@JoshFerge
Copy link
Copy Markdown
Member

When launching coding agents (GitHub Copilot, Cursor) fails with a 403 from the GitHub API, it typically means the Sentry GitHub App installation lacks the required contents:write permission. Users who installed the Sentry GitHub App before this permission was added hit this silently — the error surfaced as a cryptic "Failed to make request to coding agent... 403 Error" toast with no actionable guidance.

This PR adds structured error detection on the backend so the frontend can distinguish permission errors from generic failures and show a helpful modal that links users directly to their GitHub App installation settings to grant the missing permission.

Changes:

  • organization_coding_agents.py: Add failure_type field to LaunchFailure TypedDict
  • coding_agent.py (autofix): Detect ApiError(code=403), set failure_type="github_app_permissions", look up github_installation_id via integration_service.get_integration() using the repo's integration_id
  • coding_agent_handoff.py (explorer): Same 403 detection; looks up installation ID via integration_service.get_integrations(providers=["github"]) since explorer repos don't carry integration_id
  • All other error paths get failure_type="generic" for consistency

The frontend PR (to be merged independently) uses failure_type to decide whether to show the permissions modal or fall back to the existing error toast. The frontend is fully backwards compatible — if the backend doesn't return failure_type, it falls through to the existing error toast behavior.

…ed failure_type

When launching coding agents (Copilot or Cursor) fails with a 403 from
the GitHub API, the Sentry GitHub App installation likely lacks the
required `contents:write` permission. Previously this surfaced as a
cryptic generic error.

Now the backend detects ApiError with code 403 and returns
`failure_type: "github_app_permissions"` along with a
`github_installation_id` so the frontend can link users directly to the
correct GitHub App installation settings page to grant permissions.

Both the autofix and explorer coding agent handoff paths are updated.

Co-Authored-By: Claude <[email protected]>
@github-actions github-actions bot added the Scope: Backend Automatically applied to PRs that change backend components label Feb 18, 2026
JoshFerge added a commit that referenced this pull request Feb 18, 2026
…108452)

When launching coding agents (GitHub Copilot, Cursor) fails with a 403
from the GitHub API, it typically means the Sentry GitHub App
installation lacks the required `contents:write` permission. Previously
this surfaced as a cryptic error toast with no actionable guidance.

This PR adds a `AutofixGithubAppPermissionsModal` that explains the
issue and links users directly to the specific GitHub App installation
settings page to grant the missing permission (or falls back to the
generic installations list if the installation ID isn't known).

**Changes:**
- `autofixGithubAppPermissionsModal.tsx`: New modal component with
"Remind me later" and "Update Permissions" (links to GitHub settings)
buttons
- `useAutofix.tsx`: In `useLaunchCodingAgent`, split failures by
`failure_type` — show the permissions modal for
`"github_app_permissions"` failures, regular error toasts for others
- `useExplorerAutofix.tsx`: Same modal logic in
`triggerCodingAgentHandoff` (the explorer code path)

**Backwards compatible**: If the backend doesn't return `failure_type`
(old backend), failures without `failure_type ===
"github_app_permissions"` fall through to the existing error toast
behavior. This PR can be deployed before or after the backend PR.

**Backend PR**: #108451

---------

Co-authored-by: Claude <[email protected]>
… blocks

Add sentry_sdk.capture_exception(level="warning") to the bare
except blocks that swallow errors when looking up the GitHub
installation ID, so failures are visible in Sentry without
being treated as high-severity errors.

Co-Authored-By: Claude <[email protected]>
@JoshFerge JoshFerge force-pushed the jferg/copilot-403-backend branch from 5211a9a to 4c486c6 Compare February 18, 2026 18:03
@JoshFerge JoshFerge marked this pull request as ready for review February 18, 2026 18:03
@JoshFerge JoshFerge requested review from a team as code owners February 18, 2026 18:03
Copy link
Copy Markdown
Contributor

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

JoshFerge and others added 3 commits February 18, 2026 13:15
…g to org installations

- Use NotRequired for only the optional fields (failure_type,
  github_installation_id) instead of total=False which incorrectly made
  repo_name and error_message optional too. Also add the missing
  github_installation_id field to the TypedDict.
- Only classify 403 as github_app_permissions when using an org-installed
  integration (Cursor). A 403 from the user-authenticated Copilot client
  talking to api.githubcopilot.com is unrelated to Sentry GitHub App
  permissions and should not show the permissions modal.

Co-Authored-By: Claude <[email protected]>
…lot only

- Use NotRequired for only the optional fields (failure_type,
  github_installation_id) instead of total=False which incorrectly made
  repo_name and error_message optional too. Also add the missing
  github_installation_id field to the TypedDict.
- Only classify 403 as github_app_permissions when using the Copilot
  client (user-authenticated). The Copilot OAuth token permissions are
  the intersection of the user's GitHub permissions and the Sentry GitHub
  App installation permissions, so a Copilot 403 specifically indicates
  the GitHub App needs updated permissions.

Co-Authored-By: Claude <[email protected]>
…n 403 test

- Rename test to clarify org installation 403 now correctly returns
  failure_type="generic" (not github_app_permissions)
- Add new test verifying Copilot 403 returns failure_type="github_app_permissions"

Co-Authored-By: Claude <[email protected]>
@JoshFerge JoshFerge merged commit db103a7 into master Feb 18, 2026
77 checks passed
@JoshFerge JoshFerge deleted the jferg/copilot-403-backend branch February 18, 2026 18:49
JonasBa pushed a commit that referenced this pull request Feb 19, 2026
…rn structured failure_type (#108451)

When launching coding agents (GitHub Copilot, Cursor) fails with a 403
from the GitHub API, it typically means the Sentry GitHub App
installation lacks the required `contents:write` permission. Users who
installed the Sentry GitHub App before this permission was added hit
this silently — the error surfaced as a cryptic "Failed to make request
to coding agent... 403 Error" toast with no actionable guidance.

This PR adds structured error detection on the backend so the frontend
can distinguish permission errors from generic failures and show a
helpful modal that links users directly to their GitHub App installation
settings to grant the missing permission.

**Changes:**
- `organization_coding_agents.py`: Add `failure_type` field to
`LaunchFailure` TypedDict
- `coding_agent.py` (autofix): Detect `ApiError(code=403)`, set
`failure_type="github_app_permissions"`, look up
`github_installation_id` via `integration_service.get_integration()`
using the repo's `integration_id`
- `coding_agent_handoff.py` (explorer): Same 403 detection; looks up
installation ID via
`integration_service.get_integrations(providers=["github"])` since
explorer repos don't carry `integration_id`
- All other error paths get `failure_type="generic"` for consistency

The frontend PR (to be merged independently) uses `failure_type` to
decide whether to show the permissions modal or fall back to the
existing error toast. The frontend is fully backwards compatible — if
the backend doesn't return `failure_type`, it falls through to the
existing error toast behavior.

---------

Co-authored-by: Claude <[email protected]>
mchen-sentry pushed a commit that referenced this pull request Feb 24, 2026
…108452)

When launching coding agents (GitHub Copilot, Cursor) fails with a 403
from the GitHub API, it typically means the Sentry GitHub App
installation lacks the required `contents:write` permission. Previously
this surfaced as a cryptic error toast with no actionable guidance.

This PR adds a `AutofixGithubAppPermissionsModal` that explains the
issue and links users directly to the specific GitHub App installation
settings page to grant the missing permission (or falls back to the
generic installations list if the installation ID isn't known).

**Changes:**
- `autofixGithubAppPermissionsModal.tsx`: New modal component with
"Remind me later" and "Update Permissions" (links to GitHub settings)
buttons
- `useAutofix.tsx`: In `useLaunchCodingAgent`, split failures by
`failure_type` — show the permissions modal for
`"github_app_permissions"` failures, regular error toasts for others
- `useExplorerAutofix.tsx`: Same modal logic in
`triggerCodingAgentHandoff` (the explorer code path)

**Backwards compatible**: If the backend doesn't return `failure_type`
(old backend), failures without `failure_type ===
"github_app_permissions"` fall through to the existing error toast
behavior. This PR can be deployed before or after the backend PR.

**Backend PR**: #108451

---------

Co-authored-by: Claude <[email protected]>
mchen-sentry pushed a commit that referenced this pull request Feb 24, 2026
…rn structured failure_type (#108451)

When launching coding agents (GitHub Copilot, Cursor) fails with a 403
from the GitHub API, it typically means the Sentry GitHub App
installation lacks the required `contents:write` permission. Users who
installed the Sentry GitHub App before this permission was added hit
this silently — the error surfaced as a cryptic "Failed to make request
to coding agent... 403 Error" toast with no actionable guidance.

This PR adds structured error detection on the backend so the frontend
can distinguish permission errors from generic failures and show a
helpful modal that links users directly to their GitHub App installation
settings to grant the missing permission.

**Changes:**
- `organization_coding_agents.py`: Add `failure_type` field to
`LaunchFailure` TypedDict
- `coding_agent.py` (autofix): Detect `ApiError(code=403)`, set
`failure_type="github_app_permissions"`, look up
`github_installation_id` via `integration_service.get_integration()`
using the repo's `integration_id`
- `coding_agent_handoff.py` (explorer): Same 403 detection; looks up
installation ID via
`integration_service.get_integrations(providers=["github"])` since
explorer repos don't carry `integration_id`
- All other error paths get `failure_type="generic"` for consistency

The frontend PR (to be merged independently) uses `failure_type` to
decide whether to show the permissions modal or fall back to the
existing error toast. The frontend is fully backwards compatible — if
the backend doesn't return `failure_type`, it falls through to the
existing error toast behavior.

---------

Co-authored-by: Claude <[email protected]>
@github-actions github-actions bot locked and limited conversation to collaborators Mar 6, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

claude-code-assisted Scope: Backend Automatically applied to PRs that change backend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants