{"record":{"id":"f490825ac0a62b4e","repo":"vitest-dev/vitest","slug":"failed-to-create-vitest-api-token-at-tokenpaths","errorCode":null,"errorMessage":"Failed to create Vitest API token at ${tokenPaths.join(' or ')}","messagePattern":"Failed to create Vitest API token at (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/config/apiToken.ts","lineNumber":56,"sourceCode":"  }\n  catch {}\n  return { token, tokenCreated: true }\n}\n\nexport function resolveApiToken(root: string): { token: string; tokenCreated: boolean; tokenPath: string } {\n  const tokenPaths = [\n    join(getUserDataDir(), 'vitest', API_TOKEN_FILE),\n    join(searchForWorkspaceRoot(root), 'node_modules/.vitest', API_TOKEN_FILE),\n  ]\n\n  for (const tokenPath of tokenPaths) {\n    try {\n      return { ...resolveTokenFromPath(tokenPath), tokenPath }\n    }\n    catch {}\n  }\n\n  throw new Error(`Failed to create Vitest API token at ${tokenPaths.join(' or ')}`)\n}\n","sourceCodeStart":38,"sourceCodeEnd":58,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/vitest/src/node/config/apiToken.ts#L38-L58","documentation":"`resolveApiToken` tries two token locations — `$XDG_DATA_HOME/vitest/.vitest-secret-token` (or platform equivalent) and `<workspace>/node_modules/.vitest/.vitest-secret-token`. Each is created via `resolveTokenFromPath`, which reads an existing token or generates a UUID and writes it with restrictive perms. If both attempts throw (typically FS permission or quota errors), the function gives up and reports both candidate paths.","triggerScenarios":"Read-only home directory AND read-only/wrapped `node_modules` (pnnpm virtual store, immutable container, `npm pack` tarball); disk full or quota exceeded when writing the token; SELinux/AppArmor denying `mkdir`/`writeFile` at both locations; running in a sandbox (browser/worker) where `fs` is shimmed and throws.","commonSituations":"CI images mounted read-only; Docker containers running as a uid without write access to `$HOME`; `--read-only` filesystem flags; corporate-locked home directories; Vitest UI/browser mode where the API token gates the WebSocket.","solutions":["Ensure `$HOME` (or `$XDG_DATA_HOME`) is writable, or run in a workspace whose `node_modules` is writable.","Mount a writable volume for the user data dir in containers: `-v vitest-data:/home/node/.local/share`.","Pre-create the token file with `0600` perms containing a UUID so Vitest only needs read access.","If sandboxed, disable the API/UI feature that requires the token, or run Vitest with the appropriate `--allow-fs`/sandbox settings."],"exampleFix":"# before — read-only HOME and node_modules in CI\ndocker run --read-only myimage npx vitest --ui\n\n# after — writable data dir\nmkdir -p vitest-data\ndocker run -v \"$PWD/vitest-data:/home/node/.local/share/vitest\" myimage npx vitest --ui","handlingStrategy":"try-catch","validationCode":"import { existsSync, mkdirSync } from 'node:fs'\nimport { join } from 'node:path'\n\nfunction ensureWritableTokenDir(root: string): string[] {\n  const candidates = [\n    join(process.env.XDG_DATA_HOME || `${process.env.HOME}/.local/share`, 'vitest'),\n    join(root, 'node_modules/.vitest'),\n  ]\n  for (const dir of candidates) {\n    try {\n      mkdirSync(dir, { recursive: true, mode: 0o700 })\n      return [dir]\n    } catch {}\n  }\n  throw new Error('No writable token directory; check HOME/node_modules perms')\n}","typeGuard":null,"tryCatchPattern":"try {\n  resolveApiToken(workspaceRoot)\n} catch (e) {\n  if (/Failed to create Vitest API token/.test((e as Error).message)) {\n    // surface a friendlier message + guidance, then exit or disable UI mode\n    console.error('Vitest needs a writable token dir. Set $XDG_DATA_HOME to a writable path.')\n    process.exit(1)\n  }\n  throw e\n}","preventionTips":["Ensure `$HOME` or `$XDG_DATA_HOME` is writable in CI containers.","Avoid `--read-only` root filesystems when using `--ui`/browser mode.","Pre-create the token file with `0600` perms to require only read access."],"tags":["api-token","filesystem","permissions","ui","ci"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}