vitest >=5.0.0 changed what `-t` does. The pattern is matched against the full name: the enclosing suite names and the test name joined with ' > ' (the same string shown in the reporter output). 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/namepattern";
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) : "") };
}

write("math.test.mjs", [
  "import { describe, test } from 'vitest'",
  "import { writeFileSync } from 'node:fs'",
  "describe('math', () => {",
  "  test('adds', () => { writeFileSync(new URL('./ran.txt', import.meta.url), 'yes') })",
  "})",
].join("\n") + "\n");
const r = vitest(["run", "-t", "math > adds", "--reporter=json", "--outputFile=report.json"]);
console.log(r.out);
const reportFile = path.join(dir, "report.json");
if (!fs.existsSync(reportFile)) {
  console.error("ERROR: vitest wrote no JSON report (exit " + r.status + ")");
  process.exit(2);
}
const report = JSON.parse(fs.readFileSync(reportFile, "utf8"));
const counts = "total " + report.numTotalTests + ", passed " + report.numPassedTests + ", failed " + report.numFailedTests + ", skipped " + report.numPendingTests;
console.log(counts);
const ran = fs.existsSync(path.join(dir, "ran.txt"));
if (ran && r.status === 0 && report.numPassedTests === 1) {
  console.log("PASS: -t 'math > adds' matched the full name math > adds");
  process.exit(0);
}
// The symptom of the old behavior: vitest ran normally and skipped the test.
if (!ran && report.numTotalTests === 1 && report.numPendingTests === 1 && report.numPassedTests === 0 && report.numFailedTests === 0) {
  console.error("FAIL: -t 'math > adds' did not run the test adds inside describe('math')");
  process.exit(1);
}
console.error("ERROR: unexpected result (" + counts + ", exit " + r.status + ")");
process.exit(2);
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/namepattern";
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) : "") };
}

write("math.test.mjs", [
  "import { describe, test } from 'vitest'",
  "import { writeFileSync } from 'node:fs'",
  "describe('math', () => {",
  "  test('adds', () => { writeFileSync(new URL('./ran.txt', import.meta.url), 'yes') })",
  "})",
].join("\n") + "\n");
const r = vitest(["run", "-t", "math > adds", "--reporter=json", "--outputFile=report.json"]);
console.log(r.out);
const reportFile = path.join(dir, "report.json");
if (!fs.existsSync(reportFile)) {
  console.error("ERROR: vitest wrote no JSON report (exit " + r.status + ")");
  process.exit(2);
}
const report = JSON.parse(fs.readFileSync(reportFile, "utf8"));
const counts = "total " + report.numTotalTests + ", passed " + report.numPassedTests + ", failed " + report.numFailedTests + ", skipped " + report.numPendingTests;
console.log(counts);
const ran = fs.existsSync(path.join(dir, "ran.txt"));
if (ran && r.status === 0 && report.numPassedTests === 1) {
  console.log("PASS: -t 'math > adds' matched the full name math > adds");
  process.exit(0);
}
// The symptom of the old behavior: vitest ran normally and skipped the test.
if (!ran && report.numTotalTests === 1 && report.numPendingTests === 1 && report.numPassedTests === 0 && report.numFailedTests === 0) {
  console.error("FAIL: -t 'math > adds' did not run the test adds inside describe('math')");
  process.exit(1);
}
console.error("ERROR: unexpected result (" + counts + ", exit " + r.status + ")");
process.exit(2);
Source

The pattern is matched against the test's full name: the enclosing suite names and the test name joined with ' > ' (the same string shown in the reporter output). For example, the test below has the full name math > adds, so it is matched by -t 'math > adds' or -t adds:

vitest.dev