vitest-dev/vitest · error · FilesNotFoundError

VITEST_FILES_NOT_FOUND

VITEST_FILES_NOT_FOUND

Error message

No test files found

What it means

FilesNotFoundError (errors.ts, code VITEST_FILES_NOT_FOUND) is thrown at core.ts:868 when specifications.length === 0 after include/exclude glob resolution. It is suppressed in watch mode combined with --changed/--related so a transient empty state doesn't kill the watcher. Any other time, vitest treats zero matched test files as a hard failure so misconfigurations aren't silently green.

Source

Thrown at packages/vitest/src/node/core.ts:868

        specifications = specifications.filter(({ testModule }) => {
          return !testModule || testModule.task.mode !== 'skip'
        })
      }

      // if run with --changed, don't exit if no tests are found
      if (!specifications.length) {
        await this._traces.$('vitest.test_run', async () => {
          await this._testRun.start([])
          await this.coverageProvider?.onTestRunStart?.()
          const coverage = await this.coverageProvider?.generateCoverage?.({ allTestsRun: true })

          await this._testRun.end([], [], coverage)
          // Report coverage for uncovered files
          await this.reportCoverage(coverage, true)
        })

        if (!this.config.watch || !(this.config.changed || this.config.related?.length)) {
          throw new FilesNotFoundError()
        }
      }

      let testModules: TestRunResult = {
        testModules: [],
        unhandledErrors: [],
      }

      if (specifications.length) {
        // populate once, update cache on watch
        await this.cache.stats.populateStats(this.config.root, specifications)

        testModules = await this.runFiles(specifications, true)
      }

      if (this.config.watch) {
        await this.report('onWatcherStart')
      }

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Check test.include / test.exclude glob patterns and the --dir / cwd you run from.
  2. Verify matching test files exist with the expected extension (.test.ts, .spec.js, etc.).
  3. Pass --passWithNoTests (or set passWithNoTests: true) if an empty run is intentional.
  4. In watch mode, use --changed/--related to allow empty runs without error.

Example fix

// before
test: { include: ['src/**/*.test.ts'] } // tests live in tests/

// after
test: { include: ['{src,tests}/**/*.test.ts'] }
Defensive patterns

Strategy: validation

Validate before calling

const { glob } = await import('tinyglobby')
const matches = await glob(testInclude, { cwd: root, absolute: false })
if (matches.length === 0 && !passWithNoTests) {
  throw new Error('Globs match no files; check test.include')
}

Type guard

function hasTestFiles(files: string[]): boolean {
  return files.length > 0
}

Try / catch

try { await vitest.runFiles(specs) }
catch (e) {
  if (e?.code === 'VITEST_FILES_NOT_FOUND' && options.allowEmpty) return { empty: true }
  throw e
}

Prevention

When it happens

Trigger: include/exclude globs match zero files; CLI --include/--exclude override strips everything; running from a directory with no matching test files; project test.include empty or wrong root.

Common situations: Wrong cwd; misconfigured include glob; test files renamed/removed; monorepo filter that excludes all packages.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/8650131dd6757c04.json. Report an issue: GitHub.