vitest-dev / vitest-dev/vitest
in `globalSetup`, wrong module version served in pnpm workspaces
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 17.1k
- Forks
- 2k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 94
Description
Describe the bug
When a pnpm workspace has multiple versions of the same dependency (e.g., @azure/core-lro@2.7.2 from a published npm package and @azure/core-lro@3.x from a workspace link), vitest serves the wrong version to some importers, causing:
SyntaxError: [vite] The requested module '@azure/core-lro' does not provide an export named 'deserializeState'
Root cause: The configEnvironment hook in vitest's VitestResolver plugin returns early for the __vitest__ environment (line: if (name === "__vitest_vm__" || name === "__vitest__") return;). This skips setting resolve.noExternal = true for the main test environment. Without this, Vite's import analysis plugin treats bare specifiers of node_modules packages as "external" and does not resolve them during transform, leaving raw bare specifiers in the transformed code.
This triggers a cascade of bugs:
- Vite's
createIsExternalcaches externalization decisions by bare specifier (theprocessedIdsmap), ignoring the importer. Once@azure/core-lrois deemed external for one importer, ALL importers get the same result. - Vite's module runner caches modules by URL (
urlToIdModuleMap). The bare specifier@azure/core-lromaps to whichever version was resolved first (2.7.2), and all subsequent importers get that cached module. - The
{ cache: true }protocol between client and server doesn't carry module identity. The server resolves the bare specifier to the correct version (3.x), sees it was already transformed, and returns{ cache: true }. The client interprets this as "use what you have" and serves the wrong version (2.7.2).
Workaround: Add resolve.dedupe: ["@azure/core-lro"] to vitest.config.ts. This forces Vite's import analysis to resolve the bare specifier from the project root, producing a consistent /@fs/... URL that bypasses all three cache issues.
Reproduction
https://github.com/Azure/azure-sdk-for-js
git clone https://github.com/Azure/azure-sdk-for-js.git
cd azure-sdk-for-js
git checkout cd25924f9c263e012f50a447a770ac68d703d2a4
pnpm install
cd sdk/batch/batch
npx vitest run --no-coverage test/files.spec.ts
Expected: Tests pass (or fail for non-resolution reasons)
Actual: SyntaxError: The requested module '@azure/core-lro' does not provide an export named 'deserializeState'
Steps to reproduce
The dependency tree that triggers this:
@azure/batch(test target) depends on:@azure/arm-batch(workspace link) →@azure/core-lroworkspace (3.x, hasdeserializeState)@azure/arm-resources@5.2.0(published npm) →@azure/core-lro@2.7.2(nodeserializeState)
The arm-resources package uses ESM syntax without "type": "module" in package.json, so vitest's shouldExternalize returns false for its files — they're transformed by Vite. During transform, Vite's import analysis encounters import { ... } from "@azure/core-lro":
shouldExternalize(environment, "@azure/core-lro", "arm-resources/deployments.js")→ callscreateIsExternal→ resolves to 2.7.2 (in node_modules) →canExternalizeFile→ true → bare specifier NOT resolved → cached inprocessedIds["@azure/core-lro"] = trueshouldExternalize(environment, "@azure/core-lro", "arm-batch/pollingHelpers.js")→processedIds.has("@azure/core-lro")→ returns cachedtrue→ bare specifier NOT resolved (even though this importer should get 3.x)- Module runner receives
__vite_ssr_import__("@azure/core-lro")from both importers → first resolution (2.7.2) cached inurlToIdModuleMap["@azure/core-lro"]→ second importer gets stale 2.7.2 → crash
System Info
vitest/4.1.2 linux-x64 node-v22.22.1
vite/7.3.1
pnpm/10.33.0
Used Package Manager
pnpm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the VitestResolver plugin's configEnvironment hook and reproduce the issue with the provided Azure SDK checkout and npx vitest run --no-coverage test/files.spec.ts. Trace how the vitest environment sets resolution options and verify that importers using different dependency versions resolve and serve the correct module without the export error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript, vite
- Domain
- testing, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100