Skip to content

feat: prevent race condition dev-only error - #2789

Merged
posva merged 2 commits into
vuejs:mainfrom
meihao550:fix/router-view-null-devtools-instance
Aug 19, 2026
Merged

feat: prevent race condition dev-only error#2789
posva merged 2 commits into
vuejs:mainfrom
meihao550:fix/router-view-null-devtools-instance

Conversation

@meihao550

@meihao550 meihao550 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

What kind of change does this PR introduce?

Bug fix.

Did you add tests for your changes?

No. Reliably reproducing the null state inside @vue/test-utils + happy-dom requires an SSR/hydration timing race that does not occur in the current test harness. The fix is a one-line defensive null check that has no impact when instance is already defined, so a regression test would only exercise the untouched code path. Happy to add one if a reviewer can suggest a stable reproduction pattern.

If relevant, did you update the documentation?

No documentation change needed.

Summary

Under certain rendering conditions — observed in a Nuxt 4 SSR app with @nuxt/contentcomponent.ref.i in RouterView.ts is null when the dev-only devtools branch runs. The unguarded instance.__vrv_devtools = info assignment then throws:

TypeError: null is not an object (evaluating 'instance.__vrv_devtools = info')

crashing the app on first render.

Change

 internalInstances.forEach(instance => {
   // @ts-expect-error
-  instance.__vrv_devtools = info
+  if (instance) instance.__vrv_devtools = info
 })

Why this is safe

  • The block is guarded by __DEV__ || __FEATURE_PROD_DEVTOOLS__ and isBrowser, so production builds are unaffected.
  • When instance is truthy the behavior is unchanged.
  • When instance is null, the devtools info is simply not attached to that entry. RouterView re-runs this code on subsequent renders / re-mounts, so no persistent state is lost.

Reproduction steps

  1. Create a fresh Nuxt 4 project.
  2. Install @nuxt/content (v3.15.2) and register it in nuxt.config.ts:
    export default defineNuxtConfig({
      modules: ['@nuxt/content']
    })
  3. Add a minimal page app/pages/index.vue:
    <template><div>hello</div></template>
  4. Run npm run dev and open http://localhost:3000.
  5. The page renders briefly, then the app crashes with the TypeError shown above.

Environment: Nuxt 4.5.2, @nuxt/content 3.15.2, vue-router 5.2.0, Vue 3.5.41.


Non-native English speaker; apologies for any awkward phrasing.

Summary by CodeRabbit

  • Bug Fixes
    • Improved devtools metadata handling to prevent errors when an internal component instance is unavailable.
    • Added safeguards for potential server-side rendering timing conditions.

@netlify

netlify Bot commented Aug 18, 2026

Copy link
Copy Markdown

Deploy Preview for vue-router canceled.

Name Link
🔨 Latest commit 7edaf93
🔍 Latest deploy log https://app.netlify.com/projects/vue-router/deploys/6a8593f71a5f3b0008b76759

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 09ba14e0-1e70-4a0a-b55e-d8aeccaaf02e

📥 Commits

Reviewing files that changed from the base of the PR and between 89161b8 and 7edaf93.

📒 Files selected for processing (1)
  • packages/router/src/RouterView.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/router/src/RouterView.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

RouterView now guards the __vrv_devtools metadata assignment when the internal component instance is undefined. The change also documents a possible SSR race condition.

Changes

RouterView devtools metadata

Layer / File(s) Summary
Guard devtools metadata assignment
packages/router/src/RouterView.ts
The __vrv_devtools metadata assignment now runs only when the internal component instance exists. The code documents a possible SSR race condition.

Estimated code review effort: 1 (Trivial) | ~3 minutes

Merge Risk: ⚪ Minimal · up to 7edaf

The PR adds a localized null guard in a dev-only RouterView path, preventing a first-render crash when an instance is absent while preserving existing behavior for valid instances; no actionable merge-blocking risk remains after normal checks and review.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the dev-only crash prevention caused by a race condition in the changed RouterView path.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@posva

posva commented Aug 18, 2026

Copy link
Copy Markdown
Member

The fix is fine indeed but sounds like another bug worth digging. Do you have a repro without nuxt?

@pkg-pr-new

pkg-pr-new Bot commented Aug 18, 2026

Copy link
Copy Markdown

Open in StackBlitz

pnpm add https://pkg.pr.new/vue-router@2789
npm i https://pkg.pr.new/vue-router@2789
yarn add https://pkg.pr.new/vue-router@2789.tgz

commit: 7edaf93

@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.95%. Comparing base (67babd4) to head (7edaf93).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #2789   +/-   ##
=======================================
  Coverage   85.95%   85.95%           
=======================================
  Files          74       74           
  Lines        5895     5895           
  Branches     1893     1894    +1     
=======================================
  Hits         5067     5067           
  Misses        732      732           
  Partials       96       96           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@meihao550

Copy link
Copy Markdown
Contributor Author

The fix is fine indeed but sounds like another bug worth digging. Do you have a repro without nuxt?

Thanks for your reply

At the moment, I have only been able to reproduce it in a Nuxt 4 + @nuxt/content setup. I haven't yet found a reliable reproduction using vue-router alone.
My current suspicion is that this is related to an SSR/hydration timing issue, since component.ref.i appears to be null during the devtools registration path, but I don't yet have enough evidence to say whether the root cause is in vue-router, Vue itself, or an interaction with Nuxt/@nuxt-content.

@meihao550

meihao550 commented Aug 18, 2026

Copy link
Copy Markdown
Contributor Author
スクリーンショット 2026-08-19 2 16 49

This is the bug caused by bug in the nuxt project
I thought It was a Vue router Issue So That's why I mentioned it

Comment thread packages/router/src/RouterView.ts
@posva posva changed the title fix(RouterView): guard against null instance when assigning __vrv_dev… feat: guard against null instance when assigning __vrv_dev… Aug 19, 2026
@posva posva changed the title feat: guard against null instance when assigning __vrv_dev… feat: prevent race condition dev-only error Aug 19, 2026
@posva
posva merged commit d2b87d5 into vuejs:main Aug 19, 2026
10 checks passed
asbjornu added a commit to asbjornu/ddd-web-api that referenced this pull request Sep 3, 2026
vue-router 5.2.0 has a dev-only race in RouterView.ts: it assigns
instance.__vrv_devtools = info without checking instance is non-null,
crashing elevator-ui with "null is not an object (evaluating
'instance.__vrv_devtools = info')" on first render.

Fixed upstream in vuejs/router#2789, released in vue-router 5.3.0.
Bump elevator-ui's declared range from ^5.2.0 to ^5.3.1 and refresh
the lockfile.

Not a code smell in this codebase -- an upstream dependency bug.
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.

2 participants