vitest-dev/vitest · error · Error
Cannot set concurrency id because there are no valid free id
Error message
Cannot set concurrency id because there are no valid free ids.
What it means
Internal assertion in Pool.getConcurrencyId: it scans the workerIds map for the first free id but finds none. workerIds is initialized in setMaxWorkers to exactly maxWorkers entries (1..maxWorkers), so having no free id while scheduling a new task means more tasks were started in parallel than maxWorkers allows — an invariant violation in the scheduler.
Source
Thrown at packages/vitest/src/node/pools/pool.ts:278
if (customPool != null && customPool.name === task.worker) {
return new PoolRunner(options, customPool.createPoolWorker(options))
}
throw new Error(`Runner ${task.worker} is not supported. Test files: ${formatFiles(task)}.`)
}
private getConcurrencyId() {
let concurrencyId: number | undefined
this.workerIds.forEach((state, id) => {
if (state && concurrencyId == null) {
concurrencyId = id
this.workerIds.set(id, false)
}
})
if (concurrencyId == null) {
throw new Error('Cannot set concurrency id because there are no valid free ids.')
}
return concurrencyId
}
private freeWorkerId(id: number) {
this.workerIds.set(id, true)
}
}
function withResolvers() {
let resolve = () => {}
let reject = (_error: unknown) => {}
const promise = new Promise<void>((res, rej) => {
resolve = res
reject = rej
})View on GitHub (pinned to d568f8ce37)
Solutions
- Report as a Vitest bug with reproduction; this is a scheduler invariant, not a config error.
- Verify maxWorkers is a positive integer (>=1) in config to rule out a 0-sizing edge case.
- Retry with a different pool ('threads' vs 'forks') to see if the bug is pool-specific.
- Avoid mixing isolate:false runner reuse if it correlates with the failure.
Defensive patterns
Strategy: try-catch
Validate before calling
// Ensure maxWorkers is a positive integer to avoid 0-sizing the id map
function validateMaxWorkers(maxWorkers) {
if (maxWorkers != null && (!Number.isInteger(maxWorkers) || maxWorkers < 1)) {
throw new Error(`maxWorkers must be a positive integer, got ${maxWorkers}`)
}
} Try / catch
try {
await vitest.start()
} catch (e) {
if (e.message === 'Cannot set concurrency id because there are no valid free ids.') {
console.error('Pool scheduler invariant violated — report as a Vitest bug.')
}
throw e
} Prevention
- Keep maxWorkers a positive integer (>=1) in config.
- Pin stable Vitest versions; report persistent scheduler bugs with reproduction.
- Try an alternate pool (threads vs forks) to isolate pool-specific regressions.
When it happens
Trigger: schedule() starts a task and calls getConcurrencyId() at packages/vitest/src/node/pools/pool.ts:267-278, but every id in workerIds is already marked used. This implies the activeTasks count exceeded maxWorkers or workerIds was not sized correctly via setMaxWorkers.
Common situations: An internal scheduling bug where activeTasks.length guard at pool.ts:68 is bypassed; maxWorkers set to 0 by a config edge case; a regression in id freeing (freeWorkerId).
Related errors
- [vitest-pool]: Cannot run tasks while pool is cancelling
- Isolated tasks should not share runners
- Cannot find the environment. This is a bug in Vitest.
- The browser server was not initialized${project.name ? ` for
- Orchestrator not found for session ${sessionId}. This is a b
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/2c50a41ab2cc777a.json.
Report an issue: GitHub.