{"record":{"id":"0f5640a129e2471d","repo":"vitest-dev/vitest","slug":"the-file-relative-parentconfig-root-file-mu","errorCode":null,"errorMessage":"The file \"${relative(parentConfig.root, file)}\" must start with \"vitest.config\"/\"vite.config\" or match the pattern \"(vitest|vite).*.config.*\" to be a valid project config.","messagePattern":"The file \"(.+?)\" must start with \"vitest\\.config\"/\"vite\\.config\" or match the pattern \"\\(vitest\\|vite\\)\\.\\*\\.config\\.\\*\" to be a valid project config\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/projects/resolveProjects.ts","lineNumber":1190,"sourceCode":"\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)\n          if (configFile) {\n            projectsConfigFiles.push(configFile)\n          }\n          else {\n            const directory = file.at(-1) === '/' ? file : `${file}/`\n            nonConfigProjectDirectories.push(directory)\n          }\n        }","sourceCodeStart":1172,"sourceCodeEnd":1208,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/node/projects/resolveProjects.ts#L1172-L1208","documentation":"A file referenced directly by a `projects` string must satisfy Vitest's config naming convention (`CONFIG_REGEXP`): the basename must start with `vitest.config`/`vite.config` or match `(vitest|vite).*.config.*`. This stops arbitrary modules (test files, setup files) from being loaded as project configs.","triggerScenarios":"`projects: ['./setup.ts']` where `basename(file)` fails `CONFIG_REGEXP.test(name)` after the file passed the existence check.","commonSituations":"Pointing `projects` at a setup file, a test file, or a config with a non-standard name (e.g. `vit.config.ts`).","solutions":["Rename the file to follow `vitest.config.*` / `vite.config.*` (or `(vitest|vite).*.config.*`, e.g. `vitest.unit.config.ts`).","If the file genuinely isn't a project config, remove it from `projects`."],"exampleFix":"// before\nexport default defineConfig({ test: { projects: ['./test-setup.ts'] } })\n\n// after: rename the file on disk to vitest.config.ts (or vite.config.ts)\nexport default defineConfig({ test: { projects: ['./vitest.config.ts'] } })","handlingStrategy":"validation","validationCode":"import { basename } from 'node:path'\nconst CONFIG_REGEXP = /^(vitest|vite)(\\..*)?\\.config\\..+$/\n\nfunction assertProjectsFileNamed(root: string, projects: unknown[]) {\n  for (const def of projects) {\n    if (typeof def !== 'string' || /[*/?]/.test(def)) continue\n    const file = resolve(root, def)\n    const name = basename(file)\n    if (existsSync(file) && statSync(file).isFile() && !CONFIG_REGEXP.test(name)\n        && !(name.startsWith('vitest.config') || name.startsWith('vite.config'))) {\n      throw new Error(`'${name}' is not a valid project config name; rename to vitest.config.*/vite.config.*.`)\n    }\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Adopt the `vitest.config.{ts,js}` (or `vite.config.*`) naming everywhere.","Use the `(vitest|vite).*.config.*` form for environment-specific configs (e.g. `vitest.unit.config.ts`)."],"tags":["config","projects","naming"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}