Skip to content

fix(router-core): handle skipped view transition promises - #8802

Open
unjica wants to merge 1 commit into
TanStack:mainfrom
unjica:fix/view-transition-unhandled-rejections
Open

unjica wants to merge 1 commit into
TanStack:mainfrom
unjica:fix/view-transition-unhandled-rejections

Conversation

@unjica

@unjica unjica commented Oct 23, 2026 •

Copy link
Copy Markdown

Fixes #8776

🎯 Changes

startViewTransition only returned updateCallbackDone, so when the browser skips a transition (two navigations within ~1 frame) the rejected ready / finished promises were unhandled (AbortError: Transition was skipped).

const transition = document.startViewTransition(params)
transition.ready?.catch(() => {})
transition.finished?.catch(() => {})
return transition.updateCallbackDone

updateCallbackDone is returned unchanged, so update errors still propagate.

Added packages/router-core/tests/view-transition.test.ts (navigation with rejecting ready/finished, missing optional promises, updateCallbackDone identity + rejection). The first test fails without the fix.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with the relevant test commands, or tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

Ran locally: test:unit, test:types, test:eslint, test:build for router-core, react-router, solid-router, vue-router — all pass. The viewTransition e2e tests couldn't launch Chromium in my sandbox, so they were not run.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

AI disclosure: the change and test were drafted with an AI coding agent (Codex) and reviewed before submitting.

Summary by CodeRabbit

  • Bug Fixes
    • Navigation now completes when a view transition is skipped, even if its readiness or completion promises reject.
    • Navigation also succeeds when optional transition promises are unavailable.
    • Rejections from the transition update remain observable to callers.

Handle optional ready and finished promise rejections without changing the
updateCallbackDone promise or its rejection semantics. Add public-navigation
regression coverage and a router-core patch changeset.
@changeset-bot

changeset-bot Bot commented Oct 23, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e2af57b

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 23 packages
Name Type
@tanstack/router-core Patch
@tanstack/react-router Patch
@tanstack/react-start-client Patch
@tanstack/react-start-rsc Patch
@tanstack/react-start-server Patch
@tanstack/router-generator Patch
@tanstack/router-plugin Patch
@tanstack/solid-router Patch
@tanstack/solid-start-client Patch
@tanstack/solid-start-server Patch
@tanstack/start-client-core Patch
@tanstack/start-plugin-core Patch
@tanstack/start-server-core Patch
@tanstack/start-storage-context Patch
@tanstack/vue-router Patch
@tanstack/vue-start-client Patch
@tanstack/vue-start-server Patch
@tanstack/react-start Patch
@tanstack/router-cli Patch
@tanstack/router-vite-plugin Patch
@tanstack/solid-start Patch
@tanstack/start-static-server-functions Patch
@tanstack/vue-start Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@coderabbitai

coderabbitai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
📥 Commits

Reviewing files that changed from the base of the PR and between 6b9fe6d and e2af57b.

📒 Files selected for processing: 3
  • .changeset/cold-ravens-raise.md
  • packages/router-core/src/router.ts
  • packages/router-core/tests/view-transition.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 9 remain after this review.

📝 Walkthrough

The router now attaches rejection handlers to a view transition’s optional ready and finished promises. It continues to return updateCallbackDone, with tests covering rejected and absent optional promises and observable rejection of the returned promise.

Changes: View transition promise handling

Layer / File(s) Summary
Handle transition promises
packages/router-core/src/router.ts, packages/router-core/tests/view-transition.test.ts, .changeset/cold-ravens-raise.md
The router handles rejections from optional ready and finished promises and returns updateCallbackDone. Tests cover navigation when those promises reject or are absent, and verify that rejection of updateCallbackDone remains observable. The changeset records the patch.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested reviewers: sheraff

Merge Risk: ⚪ Minimal · up to e2af5

No actionable issue remains; the change is ready to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the router-core fix for skipped view transition promises and matches the main change.
Description check Passed The description explains the issue, implementation, tests, release impact, incomplete e2e coverage, and AI authorship. It follows the required template and includes a changeset.
Linked Issues check Passed Issue #8776 requires handlers for rejected ready and finished promises from started view transitions. packages/router-core/src/router.ts now attaches no-op handlers to both optional promises and…
Out of Scope Changes check Passed The changes stay within issue #8776. The source change handles skipped transition rejections. The tests verify this behavior and preserve update error behavior. The changeset documents the published f…
Full details: Linked Issues check

Explanation

Issue #8776 requires handlers for rejected ready and finished promises from started view transitions. packages/router-core/src/router.ts now attaches no-op handlers to both optional promises and returns transition.updateCallbackDone unchanged. The added tests cover rejected promises, missing optional promises, and update-promise identity and rejection.

Full details: Out of Scope Changes check

Explanation

The changes stay within issue #8776. The source change handles skipped transition rejections. The tests verify this behavior and preserve update error behavior. The changeset documents the published fix.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 2 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
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.

router.startViewTransition leaves the ready/finished promises unhandled, so a skipped transition throws an unhandled AbortError

1 participant