vitest-dev/vitest · error · Error

The projects glob matched a file

Error message

The projects glob matched a file "${relative(parentConfig.root, path)}", but it should also either start with "vitest.config"/"vite.config" or match the pattern "(vitest|vite).*.config.*.".

What it means

Like the direct-file rule (error 285) but applied to glob results: every file a `projects` glob expands to must still satisfy the config naming convention (`CONFIG_REGEXP`). A single non-config match fails the whole glob so unrelated files don't get loaded as projects.

Solutions

  1. Tighten the glob to match only config files, e.g. `./configs/vitest.config.*` or `./**/vitest.config.{ts,js}`.
  2. Move non-config files out of the globbed directory.
  3. Use the `(vitest|vite).*.config.*` pattern to name environment-specific configs so they pass `CONFIG_REGEXP`.

Example fix

// before: glob matches readme.md
export default defineConfig({ test: { projects: ['./configs/*'] } })

// after
export default defineConfig({ test: { projects: ['./configs/vitest.*.config.ts'] } })
Defensive patterns

Strategy: validation

Validate before calling

import { basename } from 'node:path'
const CONFIG_REGEXP = /^(vitest|vite)(\..*)?\.config\..+$/
import { glob } from 'tinyglobby'

async function assertGlobMatchesConfigs(root: string, pattern: string) {
  for (const path of await glob(pattern, { cwd: root, absolute: true })) {
    const name = basename(path)
    if (!CONFIG_REGEXP.test(name) && !name.startsWith('vitest.config') && !name.startsWith('vite.config')) {
      throw new Error(`glob '${pattern}' matched non-config file '${name}'. Tighten the pattern.`)
    }
  }
}

Prevention

When it happens

Trigger: A dynamic glob entry (e.g. `./configs/*`) expands and one of the matched paths' basename fails `CONFIG_REGEXP.test(name)` (non-directory path).

Common situations: Overly broad glob catching a README, `.eslintrc`, or other non-config file that happens to live in the same directory.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/14af206e4d7c9a96. Report an issue: GitHub.

Appendix: source

Thrown at packages/vitest/src/node/projects/resolveProjects.ts:1268

    const projectsFs = await glob(projectsGlobMatches, globOptions)

    projectsFs.forEach((path) => {
      // directories are allowed with a glob like `packages/*`
      // in this case every directory is treated as a project
      if (path.endsWith('/')) {
        const configFile = resolveDirectoryConfig(path)
        if (configFile) {
          projectsConfigFiles.push(configFile)
        }
        else {
          nonConfigProjectDirectories.push(path)
        }
      }
      else {
        const name = basename(path)
        if (!CONFIG_REGEXP.test(name)) {
          throw new Error(
            `The projects glob matched a file "${relative(parentConfig.root, path)}", `
            + `but it should also either start with "vitest.config"/"vite.config" `
            + `or match the pattern "(vitest|vite).*.config.*".`,
          )
        }
        projectsConfigFiles.push(path)
      }
    })
  }

  const projectConfigFiles = Array.from(new Set(projectsConfigFiles))

  return {
    projectConfigs: projectsOptions,
    nonConfigDirectories: nonConfigProjectDirectories,
    configFiles: projectConfigFiles,
  }
}

View on GitHub (pinned to 1fa9837ec2)