Skip to content

fix(start-plugin-core): use duck-type check for RunnableDevEnvironment to avoid dual-package hazard#6994

Open
sleitor wants to merge 2 commits intoTanStack:mainfrom
sleitor:fix-6982
Open

fix(start-plugin-core): use duck-type check for RunnableDevEnvironment to avoid dual-package hazard#6994
sleitor wants to merge 2 commits intoTanStack:mainfrom
sleitor:fix-6982

Conversation

@sleitor
Copy link
Contributor

@sleitor sleitor commented Mar 20, 2026

Summary

Fixes #6982

When is aliased to another package via pnpm overrides (e.g. vite: npm:@voidzero-dev/vite-plus-core@latest), two different RunnableDevEnvironment class references exist in memory. The isRunnableDevEnvironment() helper uses instanceof which returns false, causing SSR middleware to never be registered and all routes returning 404.

Changes

Replace isRunnableDevEnvironment(serverEnv) (instanceof-based) with a duck-type check 'runner' in serverEnv in packages/start-plugin-core/src/dev-server-plugin/plugin.ts.

The runner property (a public getter) is unique to RunnableDevEnvironmentFetchableDevEnvironment and DevEnvironment don't have it. The existing 'dispatchFetch' in serverEnv guard is preserved to correctly handle Nitro's FetchableDevEnvironment.

RunnableDevEnvironment is still imported as a type only (for the TypeScript cast on serverEnv.runner.import()), so no runtime instanceof check remains.

Testing

  • ESLint passes
  • Type errors in test:types are pre-existing (missing sibling package builds in standalone test run)

Summary by CodeRabbit

Bug Fixes

  • Fixed a compatibility issue when multiple versions or alternative distributions of the build tool were loaded in the same project, ensuring the plugin works reliably in complex dependency environments.

…t to avoid dual-package hazard

Replace isRunnableDevEnvironment (instanceof-based) with duck-type check
'runner' in serverEnv to avoid false negatives when vite is aliased via
pnpm overrides (e.g. vite-plus), which creates a dual-package hazard where
two different RunnableDevEnvironment class references exist in memory.

The 'runner' property (public getter) is unique to RunnableDevEnvironment
and not present on FetchableDevEnvironment or DevEnvironment.

Fixes TanStack#6982
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 20, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7fe9e726-2799-4481-832c-845f4b1a582f

📥 Commits

Reviewing files that changed from the base of the PR and between 91cc628 and 96eb75d.

📒 Files selected for processing (2)
  • .changeset/fix-6982-duck-type-runnable-dev-env.md
  • packages/start-plugin-core/src/dev-server-plugin/plugin.ts

📝 Walkthrough

Walkthrough

Added a changeset entry documenting a bug fix in @tanstack/start-plugin-core. Replaced instanceof checks with duck-typing by testing for the 'runner' property in dev server middleware guards to resolve vite alias/override issues.

Changes

Cohort / File(s) Summary
Changeset Documentation
.changeset/fix-6982-duck-type-runnable-dev-env.md
Added patch release note documenting the duck-typing fix for dual-package hazard with vite aliases.
Dev Server Plugin
packages/start-plugin-core/src/dev-server-plugin/plugin.ts
Replaced isRunnableDevEnvironment(serverEnv) instanceof check with duck-typing ('runner' in serverEnv). Added RunnableDevEnvironment type import and applied explicit type assertion on runner property access to maintain type safety.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A rabbit hops through vite's tangled maze,
Where aliases once clouded SSR's gaze—
We typed with ducks instead of instanceof chains,
Now middleware flows through dev's pathways,
And routes deliver where logic reigns! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly summarizes the main change: replacing instanceof checks with duck-typing for RunnableDevEnvironment to avoid dual-package hazard issues.
Linked Issues check ✅ Passed The PR fully implements the fix suggested in #6982: replacing instanceof checks with duck-typing for the 'runner' property, exactly as documented in the linked issue.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the dual-package hazard: the Changeset entry documents the fix and the plugin.ts modifications implement the suggested duck-typing approach without unrelated alterations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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 and usage tips.

@nx-cloud
Copy link

nx-cloud bot commented Mar 20, 2026

View your CI Pipeline Execution ↗ for commit 96eb75d

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ✅ Succeeded 9m 42s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 27s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-20 10:46:24 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 20, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@6994

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@6994

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@6994

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@6994

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@6994

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@6994

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@6994

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@6994

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@6994

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@6994

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@6994

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@6994

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@6994

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@6994

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@6994

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@6994

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@6994

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@6994

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@6994

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@6994

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@6994

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@6994

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@6994

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@6994

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@6994

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@6994

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@6994

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@6994

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@6994

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@6994

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@6994

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@6994

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@6994

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@6994

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@6994

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@6994

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@6994

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@6994

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@6994

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@6994

commit: 96eb75d

@github-actions
Copy link
Contributor

Bundle Size Benchmarks

  • Commit: 91cc62899b75
  • Measured at: 2026-03-20T10:38:13.089Z
  • Baseline source: history:91cc62899b75
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 88.56 KiB 0 B (0.00%) 279.34 KiB 76.84 KiB ▁▁▁▁▁▁▁▁███
react-router.full 91.73 KiB 0 B (0.00%) 290.07 KiB 79.48 KiB ▁▁▁▁▁▁▁▁███
solid-router.minimal 36.13 KiB 0 B (0.00%) 108.98 KiB 32.41 KiB ████████▁▁▁
solid-router.full 40.47 KiB 0 B (0.00%) 122.08 KiB 36.26 KiB ████████▁▁▁
vue-router.minimal 54.11 KiB 0 B (0.00%) 155.27 KiB 48.48 KiB ▁▁▁▁▁▁▁▁███
vue-router.full 58.89 KiB 0 B (0.00%) 170.42 KiB 52.63 KiB ▁▁▁▁▁▁▁▁███
react-start.minimal 103.00 KiB 0 B (0.00%) 327.41 KiB 89.02 KiB ▁▁▁▁▁▁▁▁███
react-start.full 106.37 KiB 0 B (0.00%) 337.72 KiB 91.83 KiB ▁▁▁▁▁▁▁▁███
solid-start.minimal 50.32 KiB 0 B (0.00%) 155.47 KiB 44.32 KiB ████████▁▁▁
solid-start.full 55.72 KiB 0 B (0.00%) 171.27 KiB 48.90 KiB ████████▁▁▁

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 20, 2026

Merging this PR will not alter performance

✅ 5 untouched benchmarks
⏩ 1 skipped benchmark1


Comparing sleitor:fix-6982 (96eb75d) with main (91cc628)

Open in CodSpeed

Footnotes

  1. 1 benchmark was skipped, so the baseline result was used instead. If it was deleted from the codebase, click here and archive it to remove it from the performance reports.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

start-plugin-core: instanceof RunnableDevEnvironment fails with vite-plus alias (dual-package hazard)

1 participant