{"id":"0daa5ae350a435ba","repo":"vitest-dev/vitest","slug":"projects-definition-references-a-non-existing-file","errorCode":null,"errorMessage":"Projects definition references a non-existing file or a directory: ${file}","messagePattern":"Projects definition references a non-existing file or a directory: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/projects/resolveProjects.ts","lineNumber":985,"sourceCode":"  // custom config files that were specified directly or resolved from a directory\n  const projectsConfigFiles: string[] = []\n\n  // custom glob matches that should be resolved as directories or config files\n  const projectsGlobMatches: string[] = []\n\n  // directories that don't have a config file inside, but should be treated as projects\n  const nonConfigProjectDirectories: string[] = []\n\n  for (const definition of projectsDefinition) {\n    if (typeof definition === 'string') {\n      const stringOption = definition.replace('<rootDir>', parentConfig.root)\n      // if the string doesn't contain a glob, we can resolve it directly\n      // ['./vitest.config.js']\n      if (!isDynamicPattern(stringOption)) {\n        const file = resolve(parentConfig.root, stringOption)\n\n        if (!existsSync(file)) {\n          throw new Error(`Projects definition references a non-existing file or a directory: ${file}`)\n        }\n\n        const stats = statSync(file)\n        // user can specify a config file directly\n        if (stats.isFile()) {\n          const name = basename(file)\n          if (!CONFIG_REGEXP.test(name)) {\n            throw new Error(\n              `The file \"${relative(parentConfig.root, file)}\" must start with \"vitest.config\"/\"vite.config\" `\n              + `or match the pattern \"(vitest|vite).*.config.*\" to be a valid project config.`,\n            )\n          }\n\n          projectsConfigFiles.push(file)\n        }\n        // user can specify a directory that should be used as a project\n        else if (stats.isDirectory()) {\n          const configFile = resolveDirectoryConfig(file)","sourceCodeStart":967,"sourceCodeEnd":1003,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/projects/resolveProjects.ts#L967-L1003","documentation":"In resolveTestProjectConfigs (resolveProjects.ts:982-986), a string entry in the projects array that isn't a glob is resolved to an absolute path and checked with existsSync. If the file or directory doesn't exist on disk, Vitest throws naming the resolved path. This catches typos and stale references before config resolution.","triggerScenarios":"projects: ['./vitest.unit.config.ts'] where the file doesn't exist; projects: ['packages/foo'] after packages/foo was renamed/deleted; a relative path that resolves against the wrong root; using <rootDir> substitution that yields a non-existent path.","commonSituations":"Renaming or deleting a config file/directory without updating the workspace entry; monorepo restructure; typo in the path; CI checkout missing a workspace package.","solutions":["Verify the path exists: run ls on the resolved absolute path printed in the error.","Fix the typo or update the entry to the new location.","If the project was removed intentionally, delete the entry from the projects array.","Use a glob (e.g. 'packages/*/vitest.config.ts') instead of a hardcoded path to be resilient to layout changes."],"exampleFix":"// before\nexport default defineConfig({ test: { projects: ['./vitest.unit.config.ts'] } }) // missing\n\n// after\nexport default defineConfig({ test: { projects: ['./vitest.unit.config.mts'] } }) // correct extension","handlingStrategy":"validation","validationCode":"import { existsSync } from 'node:fs'\nimport { resolve } from 'node:path'\nfor (const def of definitions) {\n  if (typeof def === 'string' && !def.includes('*')) {\n    const abs = resolve(root, def)\n    if (!existsSync(abs)) throw new Error(`projects entry '${def}' resolves to non-existing path: ${abs}`)\n  }\n}","typeGuard":"function pathExists(p: string): boolean { return existsSync(p) }","tryCatchPattern":null,"preventionTips":["Double-check paths after renames/deletes.","Prefer globs over hard-coded paths for resilience.","Add a CI step that verifies workspace entries resolve."],"tags":["projects","filesystem","path","configuration"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}