vitest-dev/vitest · error · Error

Failed to create Vitest API token at ${tokenPaths.join(' or

Error message

Failed to create Vitest API token at ${tokenPaths.join(' or ')}

What it means

Thrown by resolveApiToken() when it fails to create or read the Vitest API token at both candidate locations: the per-user data dir (XDG_DATA_HOME/Library/Application Support/LOCALAPPDATA) and `<workspace>/node_modules/.vitest`. The token secures communication between the Vitest server and its API clients; if neither location is writable/readable, the API cannot start securely.

Source

Thrown at packages/vitest/src/node/config/apiToken.ts:56

  }
  catch {}
  return { token, tokenCreated: true }
}

export function resolveApiToken(root: string): { token: string; tokenCreated: boolean; tokenPath: string } {
  const tokenPaths = [
    join(getUserDataDir(), 'vitest', API_TOKEN_FILE),
    join(searchForWorkspaceRoot(root), 'node_modules/.vitest', API_TOKEN_FILE),
  ]

  for (const tokenPath of tokenPaths) {
    try {
      return { ...resolveTokenFromPath(tokenPath), tokenPath }
    }
    catch {}
  }

  throw new Error(`Failed to create Vitest API token at ${tokenPaths.join(' or ')}`)
}

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Ensure the user data dir is writable: set XDG_DATA_HOME to a writable path, or fix permissions on ~/.local/share (Linux), ~/Library/Application Support (macOS), LOCALAPPDATA (Windows).
  2. Ensure node_modules exists and is writable inside the workspace root (run `pnpm install` / `npm install`).
  3. In read-only CI, mount a writable tmpfs at the data dir or node_modules/.vitest.
  4. Avoid running Vitest as a user without write access to either location.

Example fix

# before: read-only fs, both paths fail
# after (CI): set a writable data dir
export XDG_DATA_HOME=/tmp/vitest-data
vitest run
Defensive patterns

Strategy: validation

Validate before calling

import { access } from 'node:fs/promises'
async function assertWritableDir(dir: string) {
  try { await access(dir, await import('node:fs/promises').then(() => undefined)) }
  catch { /* fall through */ }
  const { mkdir } = await import('node:fs/promises')
  await mkdir(dir, { recursive: true, mode: 0o700 })
}

Try / catch

try {
  resolveApiToken(root)
} catch (e) {
  if (e instanceof Error && e.message.startsWith('Failed to create Vitest API token')) {
    process.env.XDG_DATA_HOME = '/tmp/vitest-data'
    resolveApiToken(root)
  } else throw e
}

Prevention

When it happens

Trigger: Both token paths are unwritable: mkdirSync/writeFileSync throw inside resolveTokenFromPath for the user-data dir AND the node_modules/.vitest dir (e.g. read-only filesystem, permission denied, no node_modules). The outer loop swallows each error and, after exhausting both, throws.

Common situations: Running in a read-only container/filesystem (some CI sandboxes); HOME/XDG_DATA_HOME unset and home dir unwritable; node_modules absent and the workspace root not writable; restrictive podman/docker SELinux policies; npm install with `--no-save` leaving no writable node_modules.


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/f490825ac0a62b4e.json. Report an issue: GitHub.