{"record":{"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/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/node/optimizer/rolldownDepPlugin.ts#L292-L328","documentation":"Injected at runtime by `vite:dep-optimizer`'s rolldown plugin into the pre-bundled module for an optional peer dependency that could not be resolved. When a dep declares an optional peer dep that is not installed, Vite externalizes it under a special namespace and emits code that throws this message in the browser when the module is actually imported. It is a lazy error: optimization succeeds, the failure surfaces only if the app imports that code path.","triggerScenarios":"rolldownDepPlugin.ts:310 builds `module.exports = {}; throw new Error(...)` for ids under `optionalPeerDepNamespace` (format `...:peerDep:parentDep`). Triggered in the browser when app code imports a module that transitively imports an uninstalled optional peer dependency.","commonSituations":"A UI library (parent dep) optionally relies on a peer like `react`, `vue`, `@reduxjs/toolkit`, or a charting engine that is not installed. The package marks it `peerDependenciesMeta: { optional: true }`, so installers skip it, but the bundler still sees the import. Version mismatch where the peer is installed under a different name.","solutions":["Install the missing peer: `npm install <peerDep>` (the message names both peerDep and parentDep).","If the import is dead code, configure tree-shaking or dynamic-import it so the browser never loads it.","Mark the peer as external (`build.rollupOptions.external`) if it is provided by the host environment at runtime.","Update the parent dependency; newer versions may handle the optional peer more gracefully.","If using a monorepo, ensure the peer is hoisted to where the parent dep resolves it."],"exampleFix":"// before: @some-lib optionally peers on 'chart.js' which is uninstalled\nimport Chart from '@some-lib/chart' // throws at runtime\n\n// after\n// $ npm install chart.js\nimport Chart from '@some-lib/chart'","handlingStrategy":"try-catch","validationCode":"import { createRequire } from 'node:module'\nconst require = createRequire(import.meta.url)\n\nfunction assertPeerInstalled(parentDep: string, peerDep: string) {\n  try {\n    const parentPkg = require.resolve(`${parentDep}/package.json`)\n    require.resolve(peerDep, { paths: [require('node:path').dirname(parentPkg)] })\n  } catch {\n    console.warn(`Optional peer '${peerDep}' of '${parentDep}' is missing; runtime import will throw.`)\n  }\n}","typeGuard":null,"tryCatchPattern":"// in app code that may hit the externalized optional peer\ntry {\n  const mod = await import('@some-lib/optional-feature')\n} catch (e) {\n  if (e instanceof Error && /Could not resolve \".*\" imported by \".*\"\\. Is it installed\\?/.test(e.message)) {\n    console.warn('Optional peer missing; falling back to default behavior.')\n    return null\n  }\n  throw e\n}","preventionTips":["Install optional peer deps you actually use (the error names both peerDep and parentDep).","Externalize peers provided by the host (build.rollupOptions.external) instead of letting the optimizer inject the throwing stub.","Code-split optional features so the throwing module is never loaded when the peer is absent."],"tags":["optimizer","peer-dependency","browser","resolver"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}