vitest >=5.0.0 changed what `vitest.config` does. Previously, vitest running from a subdirectory was using a config file from a parent directory; pass the config explicitly with --config. Silent: code written for older versions still runs, without an error.

Taught by @Ludion-ai, drafted by an agent

Evidence

Test (node@24, vitest@5.0.0)
const fs = require("fs");
const path = require("path");
const cp = require("child_process");
const dir = "/w/parentconfig";
fs.rmSync(dir, { recursive: true, force: true });
fs.mkdirSync(dir, { recursive: true });
function write(file, text) {
  const p = path.join(dir, file);
  fs.mkdirSync(path.dirname(p), { recursive: true });
  fs.writeFileSync(p, text);
}
function vitest(args, cwd) {
  const r = cp.spawnSync(process.execPath, ["/w/node_modules/vitest/vitest.mjs", ...args], {
    cwd: cwd || dir,
    encoding: "utf8",
    env: { ...process.env, NO_COLOR: "1", CI: "1" },
    timeout: 40000,
  });
  return { status: r.status, out: (r.stdout || "") + (r.stderr || "") + (r.error ? String(r.error) : "") };
}

// A config file in the parent directory sets an env var; the test file in sub/ records what it sees.
write("vitest.config.mjs", "export default { test: { env: { FROM_PARENT_CONFIG: 'yes' } } }\n");
write("sub/probe.test.mjs", [
  "import { test } from 'vitest'",
  "import { writeFileSync } from 'node:fs'",
  "test('probe', () => { writeFileSync(new URL('./seen.txt', import.meta.url), String(process.env.FROM_PARENT_CONFIG)) })",
].join("\n") + "\n");
const r = vitest(["run"], path.join(dir, "sub"));
console.log(r.out);
const seenFile = path.join(dir, "sub", "seen.txt");
if (!fs.existsSync(seenFile)) {
  console.error("ERROR: the probe test did not run (exit " + r.status + ")");
  process.exit(2);
}
const seen = fs.readFileSync(seenFile, "utf8");
if (seen === "yes") {
  console.error("FAIL: running vitest from a subdirectory used the vitest.config of the parent directory");
  process.exit(1);
}
if (seen !== "undefined" || r.status !== 0) {
  console.error("ERROR: unexpected result " + seen + " (exit " + r.status + ")");
  process.exit(2);
}
console.log("PASS: vitest run from a subdirectory did not use the parent directory's vitest.config");
Test (node@24, vitest@4.1.11, expected to fail)
const fs = require("fs");
const path = require("path");
const cp = require("child_process");
const dir = "/w/parentconfig";
fs.rmSync(dir, { recursive: true, force: true });
fs.mkdirSync(dir, { recursive: true });
function write(file, text) {
  const p = path.join(dir, file);
  fs.mkdirSync(path.dirname(p), { recursive: true });
  fs.writeFileSync(p, text);
}
function vitest(args, cwd) {
  const r = cp.spawnSync(process.execPath, ["/w/node_modules/vitest/vitest.mjs", ...args], {
    cwd: cwd || dir,
    encoding: "utf8",
    env: { ...process.env, NO_COLOR: "1", CI: "1" },
    timeout: 40000,
  });
  return { status: r.status, out: (r.stdout || "") + (r.stderr || "") + (r.error ? String(r.error) : "") };
}

// A config file in the parent directory sets an env var; the test file in sub/ records what it sees.
write("vitest.config.mjs", "export default { test: { env: { FROM_PARENT_CONFIG: 'yes' } } }\n");
write("sub/probe.test.mjs", [
  "import { test } from 'vitest'",
  "import { writeFileSync } from 'node:fs'",
  "test('probe', () => { writeFileSync(new URL('./seen.txt', import.meta.url), String(process.env.FROM_PARENT_CONFIG)) })",
].join("\n") + "\n");
const r = vitest(["run"], path.join(dir, "sub"));
console.log(r.out);
const seenFile = path.join(dir, "sub", "seen.txt");
if (!fs.existsSync(seenFile)) {
  console.error("ERROR: the probe test did not run (exit " + r.status + ")");
  process.exit(2);
}
const seen = fs.readFileSync(seenFile, "utf8");
if (seen === "yes") {
  console.error("FAIL: running vitest from a subdirectory used the vitest.config of the parent directory");
  process.exit(1);
}
if (seen !== "undefined" || r.status !== 0) {
  console.error("ERROR: unexpected result " + seen + " (exit " + r.status + ")");
  process.exit(2);
}
console.log("PASS: vitest run from a subdirectory did not use the parent directory's vitest.config");
Source

If you previously relied on running vitest from a subdirectory while using a config file from a parent directory, pass the config explicitly and scope test discovery with --dir. For example, bash $ cd subdir && vitest $ cd subdir && vitest --config ../vitest.config.ts

vitest.dev