vitest-dev/vitest · error · TypeError
Tag " ": retry.condition function cannot be used inside a…
Error message
Tag "${tag.name}": retry.condition function cannot be used inside a config file. Use a RegExp pattern instead, or define the function in your test file. What it means
A tag's `retry.condition` may not be a function when defined in a config file, because config files are serialized/shared across worker boundaries where functions cannot travel. Vitest detects `typeof tag.retry === 'object' && typeof tag.retry.condition === 'function'` and throws a `TypeError`, asking the user to use a RegExp pattern or move the function into the test file.
Solutions
- Replace the function with a RegExp pattern over the error message if the config supports it.
- Move the conditional retry into the test file where the function executes in-process.
- If a RegExp is insufficient, narrow the retry scope to specific tests instead of a tag.
Example fix
// before — vitest.config.ts
export default defineConfig({ test: { tags: [{
name: 'flaky',
retry: { condition: (e: Error) => /timeout/.test(e.message) },
}] } })
// after — use a RegExp pattern in config
export default defineConfig({ test: { tags: [{
name: 'flaky',
retry: { condition: /timeout/ },
}] } })
// or move the function into the test file and attach retry there Defensive patterns
Strategy: validation
Validate before calling
type RetryConfig = { condition?: RegExp; limit?: number }
function assertConfigSafeRetry(retry: unknown): void {
if (retry && typeof retry === 'object'
&& 'condition' in (retry as any)
&& typeof (retry as any).condition === 'function') {
throw new TypeError('retry.condition cannot be a function in a config file; use a RegExp')
}
}
(rawTags ?? []).forEach(t => assertConfigSafeRetry(t.retry)) Type guard
function isConfigSafeRetry(r: unknown): r is RetryConfig {
if (r == null) return true
if (typeof r !== 'object') return false
const cond = (r as any).condition
return cond === undefined || cond instanceof RegExp
} Prevention
- Use RegExp patterns for `retry.condition` in config files.
- Move function-based conditions into the test file where they run in-process.
- Lint configs for function-valued properties on serialisable config shapes.
When it happens
Trigger: `test.tags: [{ name: 'flaky', retry: { condition: (err) => err.message.includes('timeout') } }]` in `vitest.config.ts`. The same shape is fine when declared inside a test file via the runner API, because that code runs in-process.
Common situations: Migrating per-test retry conditions into shared config; reusing a function from a config preset; refactoring that moves logic from test files into config.
Related errors
- Each tag defined in "test.tags" must have a "name"…
- "snapshotFormat.compareKeys" function is not supported.
- Tag name " " is already defined in "test.tags". Tag names…
- Tag name " " is invalid. Tag names cannot contain spaces.
- Tag name " " is invalid. Tag names cannot be a logical…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/ccfd85d4a28784bb.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/node/config/resolveConfig.ts:305
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)) {
throw new Error(`Tag name "${tag.name}" is invalid. Tag names cannot contain spaces.`)
}
if (/[!()*|&]/.test(tag.name)) {
throw new Error(`Tag name "${tag.name}" is invalid. Tag names cannot contain "!", "*", "&", "|", "(", or ")".`)
}
if (/^\s*(?:and|or|not)\s*$/i.test(tag.name)) {
throw new Error(`Tag name "${tag.name}" is invalid. Tag names cannot be a logical operator like "and", "or", "not".`)
}
if (typeof tag.retry === 'object' && typeof tag.retry.condition === 'function') {
throw new TypeError(`Tag "${tag.name}": retry.condition function cannot be used inside a config file. Use a RegExp pattern instead, or define the function in your test file.`)
}
if (tag.priority != null && (typeof tag.priority !== 'number' || tag.priority < 0)) {
throw new TypeError(`Tag "${tag.name}": priority must be a non-negative number.`)
}
definedTags.add(tag.name)
})
resolved.name = typeof options.name === 'string'
? options.name
: (options.name?.label || '')
resolved.color = typeof options.name !== 'string' ? options.name?.color : undefined
if (resolved.environment === 'browser') {
throw new Error(`Looks like you set "test.environment" to "browser". To enable Browser Mode, use "test.browser.enabled" instead.`)
}
resolved.benchmark = {View on GitHub (pinned to 1fa9837ec2)