Skip to content

Revert "fix(modal): Contain render errors within the dialog" - #129728

Closed
sentry-junior[bot] wants to merge 3 commits into
masterfrom
junior/investigate/revert-129199-sudo-modal-loop
Closed

sentry-junior[bot] wants to merge 3 commits into
masterfrom
junior/investigate/revert-129199-sudo-modal-loop

Conversation

@sentry-junior

@sentry-junior sentry-junior Bot commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Reverts #129199 (cc @TkDodo for context).

What breaks

Since #129199 shipped, a Sentry employee who opens a customer-domain org page without an active superuser session gets stuck in an infinite loop. The page keeps refetching the org bootstrap requests and /api/0/authenticators/, and the sudo modal spinner never resolves, so they can't elevate.

Why

#129199 added an incrementing modalId to ModalStore and renders the modal content inside <ErrorBoundary key={modalId}>. Every openModal call now remounts the whole modal subtree. Before, a second openModal with the same component type reconciled in place.

OrganizationContextProvider calls openSudo from an effect on [user, error, organization] whenever user.isSuperuser && error.status === 403. That interacts badly with the remount:

  1. Org bootstrap 403s → effect calls openSudo → SudoModal mounts.
  2. On mount, SudoModal subscribes to the bootstrap org/teams/projects queries, which refetch because they errored.
  3. Each 403 sets a new error object in OrganizationStore → the effect re-runs → openSudo → modalId increments → SudoModal remounts → go to 2.

SudoModal waits for the bootstrap queries to settle before it fetches authenticators, so it never gets past the loading state.

Evidence

  • Prod: the frontend console log for the org-details 403 (GET /organizations/{orgSlug}/ 403 … You do not have permission) jumped from about 8 per session to about 118k lines from 23 employees, starting at about 12:56 UTC on 2026-11-03, shortly after fix(modal): Contain render errors within the dialog #129199 merged at 12:09 UTC. That's roughly 1000× baseline.
  • Jest repro: a superuser, a plain 403 ({"detail": "You do not have permission to perform this action."}) on /organizations/org-slug/, /teams/ and /projects/, rendering OrganizationContextProvider + GlobalModal with the real sudo modal, then waiting 2s:
    • master: 4666 org-details requests, 0 authenticators requests, password form never renders
    • this revert: 2 org-details requests, 1 authenticators request, password form renders

Changes

  • git revert a976243287050cb02bb60520bc4818370ed3567d. It applies cleanly and restores the 5 files touched by fix(modal): Contain render errors within the dialog #129199 to their exact pre-fix(modal): Contain render errors within the dialog #129199 contents. Nothing else reads modalId.
  • Adds static/app/views/organizationContextSudo.spec.tsx, a small regression test for the scenario above without the sleep. It waits for the password field and asserts the org request ran at most 3 times. It needs its own file because organizationContext.spec.tsx mocks openSudo. It fails on master (the password field never appears) and passes on this branch, about 3s per run and 3/3 stable locally.

Re-landing #129199

Either of these should let the error containment come back without the loop:

  • Only re-key the ErrorBoundary when it's actually showing an error (reset it on a new modalId without changing key), so a normal re-open still reconciles in place.
  • And/or make OrganizationContextProvider skip openSudo while a sudo modal is already open, so repeated 403s don't re-open it.

Ideally, the re-land keeps the regression test from this PR.

Verification

  • jest on core/modal/index.spec.tsx, errorBoundary.spec.tsx, modals/sudoModal.spec.tsx, views/organizationContext.spec.tsx, views/organizationContextSudo.spec.tsx: 5 suites, 38 tests passed. There is no modalStore spec.
  • pnpm run typecheck: passed
  • pnpm run lint:js and oxfmt --check on touched files: clean

via @lcian.

--

View Session [Sentry]

sentry-junior Bot and others added 2 commits November 3, 2026 18:39
This reverts commit a976243 (#129199).

Keying the modal's ErrorBoundary on an incrementing modalId remounts the
whole modal subtree on every openModal call. OrganizationContextProvider
calls openSudo from an effect whenever a superuser hits a 403 on the org
bootstrap. On mount, SudoModal refetches the errored bootstrap queries,
each 403 produces a new error object, the effect calls openSudo again,
and the modal remounts. Superuser elevation on a customer-domain org
loops forever and the sudo modal never gets past its loading state.

Co-Authored-By: Lorenzo Cian <17258265+lcian@users.noreply.github.com>
Renders OrganizationContextProvider with the real sudo modal and a
superuser whose org bootstrap requests 403. Fails if the modal never
reaches the password form or the org request is refetched in a loop.

Co-Authored-By: Lorenzo Cian <17258265+lcian@users.noreply.github.com>
@github-actions github-actions Bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Nov 3, 2026
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

Story previews

Preview the stories changed in this PR on the Vercel deployment:

Preview deployment: https://sentry-4ny6rzrmq.sentry.dev

The registry is emitted in TypeScript program file order, which shifts
with the modal imports removed by the revert. Only the position of
account-emails.email changes.

This branch was successfully deployed

1 active deployment
Preview — a4eb1a70 Deployed Nov 3, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants