{"record":{"id":"8953c1b1c8ad4ced","repo":"cypress-io/cypress","slug":"could-not-resolve-dep-do-you-have-angular","errorCode":null,"errorMessage":"Could not resolve \"${dep}\". Do you have \"@angular-devkit/build-angular\" and \"@angular-devkit/core\" installed?","messagePattern":"Could not resolve \"(.+?)\"\\. Do you have \"@angular-devkit/build-angular\" and \"@angular-devkit/core\" installed\\?","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"npm/webpack-dev-server/src/helpers/angularHandler.ts","lineNumber":203,"sourceCode":"    { getCommonConfig },\n    { getStylesConfig },\n    { logging },\n  ] = await Promise.all(angularCLiModules.map(async (dep) => {\n    try {\n      let depPath = require.resolve(dep, { paths: [projectRoot] })\n      // NOTE: @cypress/webpack-dev-server is a CJS package, but we need to import some ESM files and absolute imports.\n      // since import statements in TypeScript will get transpiled down to CommonJS require statements, we want to use tsx to leverage\n      // an ESM style import here, which supports CommonJS and ESM.\n      const { tsImport } = require('tsx/esm/api')\n\n      // NOTE: on Windows, fully qualified paths (ex: C:\\Users\\username\\project\\blah) need to be prefixed with `file://` to be properly resolved.\n      depPath = platform() === 'win32' ? `file://${toPosix(depPath)}` : depPath\n\n      const module = await tsImport(depPath, __filename)\n\n      return module\n    } catch (e) {\n      throw new Error(`Could not resolve \"${dep}\". Do you have \"@angular-devkit/build-angular\" and \"@angular-devkit/core\" installed?`)\n    }\n  }))\n\n  return {\n    generateBrowserWebpackConfigFromContext,\n    getCommonConfig,\n    getStylesConfig,\n    logging,\n  }\n}\n\nexport async function getAngularJson (projectRoot: string): Promise<AngularJson> {\n  // NOTE: @cypress/webpack-dev-server is a CJS package, but find-up +6.0.0 is an ESM only package.\n  // In order to dynamically import the find-up package, we need to use tsx to do so until @cypress/webpack-dev-server is an ESM-only package,\n  // which would be a breaking change to @cypress/webpack-dev-server and cypress.\n  const { tsImport } = require('tsx/esm/api')\n\n  const { findUp } = await tsImport('find-up', __filename) as typeof import('find-up')","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/cypress-io/cypress/blob/0d85fdc91230885bca0a91df278312800a48b727/npm/webpack-dev-server/src/helpers/angularHandler.ts#L185-L221","documentation":"Thrown inside the Angular CLI module loader loop when require.resolve or tsImport fails for one of the @angular-devkit modules (build-angular/src/webpack/utils, build-angular/src/index, core/src/index). The loader uses tsx's tsImport to dynamically import these ESM-only Angular packages; any failure is caught and rethrown as a single, dependency-installation-focused message. It is essentially a peer-dependency / resolution guard, not a logic error.","triggerScenarios":"Running Cypress component tests with the Angular webpack-dev-server when @angular-devkit/build-angular or @angular-devkit/core is not installed in node_modules reachable from projectRoot, when versions are mismatched (e.g. Angular 19 devkit on an Angular 18 project), or when the package was hoisted in a way that breaks require.resolve paths.","commonSituations":"Fresh clone where Angular dev dependencies were marked optional and skipped, monorepo hoisting (yarn workspaces) that places @angular-devkit outside the resolution scope, Windows path issues that the file:// prefix logic at line 197 does not cover, or a broken tsx install.","solutions":["Run `npm install --save-dev @angular-devkit/build-angular @angular-devkit/core` (or yarn/pnpm equivalent) at the project root Cypress is testing.","Verify the installed versions match the project's Angular major version (`ng version`).","If using a monorepo, ensure the package is resolvable from projectRoot — add it to the workspace's package.json or use nohoist / pnpm overrides as appropriate.","On Windows, confirm the resolved path is absolute and on the same drive; the file:// prefix logic at line 197 only fires for win32.","Reinstall tsx if the failure is inside tsImport itself (`npm ls tsx`)."],"exampleFix":"// before\n# Angular project package.json (devDependencies)\n{}\n// after\n# Angular project package.json (devDependencies)\n{\n  \"@angular-devkit/build-angular\": \"^19.0.0\",\n  \"@angular-devkit/core\": \"^19.0.0\"\n}","handlingStrategy":"validation","validationCode":"const required = [\n  '@angular-devkit/build-angular',\n  '@angular-devkit/core',\n]\nfor (const dep of required) {\n  try { require.resolve(dep, { paths: [projectRoot] }) }\n  catch { console.error(`Missing ${dep} — install it before running Cypress CT`) }\n}","typeGuard":"function canResolveAngularDevkit (projectRoot: string): boolean {\n  const deps = [\n    '@angular-devkit/build-angular/src/webpack/utils',\n    '@angular-devkit/build-angular/src/index.js',\n    '@angular-devkit/core/src/index.js',\n  ]\n  return deps.every((d) => {\n    try { require.resolve(d, { paths: [projectRoot] }); return true } catch { return false }\n  })\n}","tryCatchPattern":null,"preventionTips":["Keep @angular-devkit/build-angular and core versions aligned with the Angular major.","Run a resolution check in a pretest script.","On Windows, confirm absolute paths are on the same drive before invoking the dev server."],"tags":["angular","devkit","dependency-resolution","dev-server"],"backgroundTag":null,"analyzedSha":"0d85fdc91230885bca0a91df278312800a48b727","analyzedAt":"2026-08-12T16:24:28.056Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}