{"id":"f4bbc469a85cc0a9","repo":"vitejs/vite","slug":"could-not-resolve-peerdep-imported-by-pare","errorCode":null,"errorMessage":"Could not resolve \"${peerDep}\" imported by \"${parentDep}\". Is it installed?","messagePattern":"Could not resolve \"(.+?)\" imported by \"(.+?)\"\\. Is it installed\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/optimizer/rolldownDepPlugin.ts","lineNumber":310,"sourceCode":"            key !== '__proto__' &&\n            key !== 'constructor' &&\n            key !== 'splice'\n        ) {\n            console.warn(\\`Module \"${path}\" has been externalized for browser compatibility. Cannot access \"${path}.\\${key}\" in client code. See https://vite.dev/guide/troubleshooting.html#module-externalized-for-browser-compatibility for more details.\\`)\n        }\n        }\n    }))`,\n              }\n            }\n          }\n\n          if (id.startsWith(optionalPeerDepNamespace)) {\n            const path = id.slice(optionalPeerDepNamespace.length)\n            const [, peerDep, parentDep] = path.split(':')\n            return {\n              code:\n                'module.exports = {};' +\n                `throw new Error(\\`Could not resolve \"${peerDep}\" imported by \"${parentDep}\". Is it installed?\\`)`,\n            }\n          }\n        },\n      },\n      transform: {\n        filter: {\n          code: assetImportMetaUrlRE,\n        },\n        handler(code, id) {\n          let s: MagicString | undefined\n          const re = new RegExp(assetImportMetaUrlRE)\n          const cleanString = stripLiteral(code)\n\n          let match: RegExpExecArray | null\n          while ((match = re.exec(cleanString))) {\n            const [[startIndex, endIndex], [urlStart, urlEnd]] =\n              match.indices as Array<[number, number]>\n            if (hasViteIgnoreRE.test(code.slice(startIndex, urlStart))) continue","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/node/optimizer/rolldownDepPlugin.ts#L292-L328","documentation":"When a dependency declares a peer dependency as optional and the consumer hasn't installed it, Vite's resolve layer marks it with the `__vite-optional-peer-dep` id (resolve.ts:752). The rolldownDepPlugin's load hook converts that into a runtime module whose code throws `Could not resolve \"<peerDep>\" imported by \"<parentDep>\". Is it installed?` in the browser (rolldownDepPlugin.ts:310). This surfaces a missing optional peer at execution time rather than silently breaking.","triggerScenarios":"A pre-bundled dependency imports one of its optional peer dependencies that the user did not install; the first time the browser executes that module the thrown error fires.","commonSituations":"React component libraries with optional peer deps (e.g. an optional styling/icon peer, an optional framework adapter); packages that lazy-import an optional feature; mono-repos where a peer is hoisted away from the consuming workspace.","solutions":["Install the named peer dependency: `npm i <peerDep>` (the error quotes both peerDep and parentDep).","If you intentionally don't use that feature, ensure your code path doesn't import the module that triggers it (tree-shake / avoid the entry).","Pin a version of the parent dependency that makes the peer non-optional or bundles a fallback.","Add the parent dep to `optimizeDeps.exclude` if you'd rather resolve it yourself outside the optimizer."],"exampleFix":"// before — error: Could not resolve \"@heroicons/react\" imported by \"my-ui-lib\"\n\n// after\n// run:  npm install @heroicons/react","handlingStrategy":"validation","validationCode":"import { createRequire } from 'node:module'\nconst require = createRequire(import.meta.url)\nfunction assertPeerInstalled(parentDep: string, peerDep: string) {\n  const parentPkg = require(`${parentDep}/package.json`)\n  const peers = { ...(parentPkg.peerDependencies || {}), ...(parentPkg.peerDependenciesMeta || {}) }\n  if (peerDep in peers) {\n    try { require.resolve(peerDep) }\n    catch { throw new Error(`Optional peer '${peerDep}' of '${parentDep}' is missing. Run: npm i ${peerDep}`) }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["After installing a library, install its optional peers you actually use.","Check package.json.peerDependenciesMeta for optional peers.","Add a postinstall check that resolves each used optional peer."],"tags":["optimizer","peer-dependency","resolution","dependencies"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}