vitest-dev/vitest · error · Error
The `test.workspace` option was removed in Vitest 4. Please,
Error message
The `test.workspace` option was removed in Vitest 4. Please, migrate to `test.projects` instead. See https://vitest.dev/guide/projects for examples.
What it means
A hard breaking-change error thrown during config resolution when the resolved config still contains a `workspace` key. Vitest 4 removed `test.workspace` in favor of `test.projects` (which supports the same array-of-project-config shape plus globs). The check `'workspace' in resolved` fires unconditionally, so any presence of the old key aborts startup.
Source
Thrown at packages/vitest/src/node/config/resolveConfig.ts:249
)
resolved.retry = {
...resolved.retry,
condition: undefined,
}
}
if (options.pool && typeof options.pool !== 'string') {
resolved.pool = options.pool.name
resolved.poolRunner = options.pool
}
if ('poolOptions' in resolved) {
logger.deprecate('`test.poolOptions` was removed in Vitest 4. All previous `poolOptions` are now top-level options. Please, refer to the migration guide: https://v4.vitest.dev/guide/migration#pool-rework')
}
if ('workspace' in resolved) {
throw new Error('The `test.workspace` option was removed in Vitest 4. Please, migrate to `test.projects` instead. See https://vitest.dev/guide/projects for examples.')
}
resolved.pool ??= 'forks'
resolved.project = toArray(resolved.project)
resolved.provide ??= {}
// shallow copy tags array to avoid mutating user config
resolved.tags = [...resolved.tags || []]
const definedTags = new Set<string>()
resolved.tags.forEach((tag) => {
if (!tag.name || typeof tag.name !== 'string') {
throw new Error(`Each tag defined in "test.tags" must have a "name" property, received: ${JSON.stringify(tag)}`)
}
if (definedTags.has(tag.name)) {
throw new Error(`Tag name "${tag.name}" is already defined in "test.tags". Tag names must be unique.`)
}
if (/\s/.test(tag.name)) {View on GitHub (pinned to d568f8ce37)
Solutions
- Rename `test.workspace` to `test.projects` in your vitest.config / workspace file.
- Follow the migration guide at https://vitest.dev/guide/projects for the projects shape (globs are now supported).
- Search the repo (and any imported config presets) for `workspace:` and update all occurrences.
Example fix
// before
export default defineConfig({ test: { workspace: ['packages/*'] } })
// after
export default defineConfig({ test: { projects: ['packages/*'] } }) Defensive patterns
Strategy: validation
Validate before calling
if ('workspace' in config.test) {
throw new Error('test.workspace was removed in Vitest 4; use test.projects')
} Prevention
- Before upgrading to Vitest 4, grep the repo and config presets for `workspace:` and rename to `projects:`.
- Run the official Vitest migration codemod if available.
- Update internal docs and onboarding templates that reference test.workspace.
When it happens
Trigger: Upgrading to Vitest 4 while keeping `test: { workspace: [...] }` in vitest.config (or a workspace file). deepMerge carries the `workspace` key into resolved, and the guard throws with a migration link.
Common situations: Major-version upgrade from Vitest 2/3 to 4 without migrating config; shared config presets not yet updated; docs/tutorials still referencing the old `workspace` option.
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/6a55383271b29f87.json.
Report an issue: GitHub.