Skip to content

fix: guard React transition runtime APIs - #567

Draft
cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-7a5b
Draft

cursor[bot] wants to merge 1 commit into
mainfrom
cursor/critical-bug-investigation-7a5b

Conversation

@cursor

@cursor cursor Bot commented Aug 30, 2026 •

Copy link
Copy Markdown

Bug and impact

Recent navigation/search/course registry changes reintroduced direct runtime imports of addTransitionType and ViewTransition from react. The installed react@19.2.8 package exposes both as undefined at runtime even though the canary type declarations allow them, so rendering course paper grids/page transitions or clicking search/filter/nav controls could crash user-facing routes.

Root cause

Components imported experimental transition APIs directly from react instead of going through a runtime feature-detection wrapper. This let TypeScript/Next compile while producing runtime calls/renders against missing exports.

Fix

  • Added app/components/common/react-transition.tsx with guarded addReactTransitionType and OptionalViewTransition helpers.
  • Updated navigation, search, filter, voice, mobile tab, command palette, directional transition, and course paper grid call sites to use the guarded helpers.
  • Added scripts/test-react-transition-runtime-imports.ts to fail future unsafe imports/raw <ViewTransition> usage outside the wrapper.

Validation

  • CI=true corepack pnpm exec tsx scripts/test-react-transition-runtime-imports.ts passes and reports addTransitionType=undefined ViewTransition=undefined Activity=symbol plus no unsafe imports.
  • node -e "const r=require('react'); console.log('addTransitionType=', typeof r.addTransitionType, 'ViewTransition=', typeof r.ViewTransition, 'Activity=', typeof r.Activity)" confirms the current runtime lacks both APIs.
  • CI=true corepack pnpm build compiled successfully and finished TypeScript, then failed only during page-data collection because DATABASE_URL is unset in this environment.
Open in Web View Automation 

spent a lot of water and tokens to review your slop

Greptile Summary

This change moves experimental React transition access behind a compatibility wrapper and adds a scanner intended to prevent unsafe imports. Render validation showed that the wrapper drops valid non-function ViewTransition values, including the experimental symbol-based export. The scanner is not run by the configured automated checks and does not detect several direct React member-access forms, allowing unsafe calls to bypass the intended safeguard. These issues should be resolved before merge.

Confidence Score: 2/5

Not safe to merge until the transition wrapper accepts the supported runtime element type and the regression scanner is both comprehensive and automatically executed.

Three independently reproduced defects can disable intended transitions or allow unsupported React transition API usage to bypass the newly added safeguard.

Files Needing Attention: app/components/common/react-transition.tsx requires a presence-based runtime guard; scripts/test-react-transition-runtime-imports.ts requires broader detection and automated invocation from package and workflow configuration.

T-Rex T-Rex Logs

What T-Rex did

  • Validated the ViewTransition guard render validation by reviewing the source and the runtime scanner output.
  • Verified the validation harness for React transition scanner bypasses, including baseline output and direct-access fixtures.
  • Ran the automation audit and confirmed that direct scanner execution succeeds.
  • Compared the current wrapper behavior with the undefined-only guard and confirmed the wrapper changes described in the contract validation.
  • Audited the package manifest and CI workflows to confirm there is no scanner wiring, and validated scanner behavior across before/after fixtures with cleanup confirmed.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (3)

  1. General comment

    P1 OptionalViewTransition omits valid non-function ViewTransition element types

    • Bug
      • The function-only availability check treats React-exotic component objects and React's actual experimental ViewTransition symbol as unsupported. In the executed renders, forwardRef and memo types rendered only the child through the current component; the proposed undefined-only guard rendered the wrapper. The experimental runtime's ViewTransition is a symbol and is likewise omitted by the current guard.
    • Cause
      • typeof ViewTransition !== "function" assumes every valid React element type is callable, but React accepts exotic object types and special symbol element types.
    • Fix
      • Replace the function-only check at app/components/common/react-transition.tsx:23 with an absence check such as if (ViewTransition === undefined), and widen the local runtime type from React.ComponentType<ViewTransitionProps> to a React element-type-compatible type.

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 React transition runtime-import scanner is not part of automated validation

    • Bug
      • scripts/test-react-transition-runtime-imports.ts has no invocation in package.json, .github/workflows/deploy-appservice.yml, or azure-pipelines.yml. The normal build path (npm run build) runs synchronization scripts and next build, not this scanner. Consequently, regressions the scanner is intended to catch can merge and deploy without the scanner running.
    • Cause
      • The scanner was added as a standalone TypeScript script but was never connected to an npm validation/build script or either CI workflow.
    • Fix
      • Add a dedicated npm script (for example, test:react-transition-runtime-imports: tsx scripts/test-react-transition-runtime-imports.ts) and invoke it from the CI validation/build sequence (or a CI test job) so pull requests and deployment builds execute it.

    T-Rex Ran code and verified through T-Rex

  3. General comment

    P1 React transition runtime scanner misses direct React member access

    • Bug
      • scripts/test-react-transition-runtime-imports.ts fails to report executable direct access to unsafe transition APIs: React.addTransitionType?.(...), JSX <React.ViewTransition />, an aliased const Transition = React.ViewTransition rendered as <Transition />, and React.createElement(React.ViewTransition, ...). All four fixtures were scanned from app/ and passed unreported.
    • Cause
      • Lines 48–49 only inspect named imports for bare unsafe identifiers, while lines 65–73 only match a literal <ViewTransition> JSX tag. Neither detection path recognizes member expressions, aliases originating from member expressions, or createElement arguments.
    • Fix
      • Extend the scanner using a TypeScript/JSX AST (preferred) to detect React.addTransitionType and React.ViewTransition member expressions, track local aliases assigned from React.ViewTransition, and flag JSX/createElement usages of those aliases. Retain the current named-import checks.

    T-Rex Ran code and verified through T-Rex

Fix all with Greploop Fix All in Codex Fix All in Claude Code Fix All in Cursor

Reviews (1): Last reviewed commit: "fix: guard React transition runtime APIs" | Re-trigger Greptile

Greptile also left 3 inline comments on this PR.

Co-authored-by: theg1239 <theg1239@users.noreply.github.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
❌ Deployment failed
View logs
examcooker b2e8102 Aug 30 2026, 11:06 AM

@vercel

vercel Bot commented Aug 30, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
examcooker-dev Error Error Aug 30, 2026 11:08am

Comment on lines +23 to +25
if (typeof ViewTransition !== "function") {
return <>{children}</>;
}

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.

P1 Function-only guard drops supported ViewTransition types

OptionalViewTransition treats every non-function ViewTransition export as unavailable. React-valid element types can be exotic objects, and the experimental React runtime exposes ViewTransition as Symbol(react.view_transition). This branch therefore returns only children even when the API is available, silently disabling the transition wrapper. Check whether the export is absent instead, and type the runtime value as a React element-type-compatible value rather than ComponentType.

Artifacts

Narrow ViewTransition guard render validation source

  • Authored and executed React render validation that injects forwardRef, memo, and the experimental ViewTransition symbol into the wrapper runtime; it exercises the claimed guard failure path.

Rendered React behavior for current and proposed ViewTransition guards

  • Captured output from the executed validation shows that the current guard drops forwardRef and memo wrappers and rejects the experimental ViewTransition symbol; the proposed guard preserves them.

React transition runtime import scanner output

  • Captured output from the repository scanner confirms the installed stable React runtime has no ViewTransition export and no unsafe transition runtime imports.

View artifacts

T-Rex Ran code and verified through T-Rex

Fix in Codex Fix in Claude Code Fix in Cursor

return usages;
}

const violations: string[] = [];

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.

P1 Transition scanner never runs automatically

The scanner is a standalone script: neither package.json nor the configured workflow files invoke it. The normal npm run build path proceeds from synchronization scripts to next build without executing this check, so an unsafe transition import can be introduced and deployed without the regression guard running. Add it to an npm validation script and invoke that script from the build or automated validation path.

Artifacts

Narrow automation-audit script source

  • Shows the authored TypeScript audit that reads package.json and both configured CI workflow files for scanner references, ending with a nonzero result if any reference exists.

Normal build path without scanner invocation

  • Captures `npm run build` from `/home/user/repo`; it runs only synchronization scripts and `next build`, never the scanner, then stops on the unrelated missing DATABASE_URL configuration.

Executed automation audit reporting no scanner wiring

  • Captures the audit execution reporting zero package-script references and zero CI-workflow references to the scanner, confirming missing automation wiring.

Reference search with no configured invocation

  • Captures the exact ripgrep search of package.json and both CI configuration locations; exit code 1 and empty output show no scanner reference.

Direct scanner execution succeeds

  • Captures `CI=true node_modules/.bin/tsx scripts/test-react-transition-runtime-imports.ts` succeeding and reporting no unsafe React transition runtime imports, proving the standalone scanner is runnable.

View artifacts

T-Rex Ran code and verified through T-Rex

Fix in Codex Fix in Claude Code Fix in Cursor

Comment on lines +48 to +73
const namedImportRegex = new RegExp(`[{,]\\s*${name}\\b`);
if (namedImportRegex.test(statement)) {
matches.push(statement.replace(/\s+/g, " ").trim());
break;
}
}
}

return matches;
}

function stripComments(source: string) {
return source
.replace(/\/\*[\s\S]*?\*\//g, "")
.replace(/^\s*\/\/.*$/gm, "");
}

function getUnsafeViewTransitionUsage(source: string) {
const usages: string[] = [];
const jsxRegex = /<\/?\s*ViewTransition\b/g;

for (const match of source.matchAll(jsxRegex)) {
usages.push(match[0]);
}

return usages;

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.

P1 Scanner misses direct React transition access

The named-import and literal <ViewTransition> patterns do not detect direct member access. Executable fixtures using React.addTransitionType?.(...), <React.ViewTransition />, an alias assigned from React.ViewTransition, and React.createElement(React.ViewTransition, ...) all passed the scanner. These forms bypass the guarded wrapper and can reintroduce the unsupported-runtime failure; use a TypeScript/JSX AST check that detects React member expressions and aliases derived from them.

Artifacts

Validation harness source for React transition scanner bypasses

  • This authored TypeScript harness creates six scanned-root fixtures, invokes the real scanner, asserts expected results, and removes the fixtures; it defines the executed validation.

Baseline React transition scanner output without temporary fixtures

  • The real scanner was executed before fixtures and exited 0 with no unsafe runtime imports reported, establishing the clean baseline.

React transition scanner output with direct React access fixtures

  • The real scanner blocked both aliased named imports but passed all four direct React member-expression variants, confirming the bypass.

Temporary React transition scanner fixtures cleanup output

  • A filesystem check after the harness run confirmed the temporary scanned-root fixture directory is absent, so the fixtures were cleaned up.

View artifacts

T-Rex Ran code and verified through T-Rex

Fix in Codex Fix in Claude Code Fix in Cursor

This branch had an error being deployed

1 failed deployment
Preview – examcooker-dev — b2e81028 Deployed Aug 30, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant