{"id":"3beba4d38f81f237","repo":"vitest-dev/vitest","slug":"expected-vitest-as-the-first-argument-received","errorCode":null,"errorMessage":"Expected \"vitest\" as the first argument, received \"${arrayArgs[0]}\"","messagePattern":"Expected \"vitest\" as the first argument, received \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vitest/src/node/cli/cac.ts","lineNumber":235,"sourceCode":"  return str\n}\n\nfunction splitArgv(argv: string): string[] {\n  const reg = /(['\"])(?:(?!\\1).)+\\1/g\n  argv = argv.replace(reg, match => match.replace(/\\s/g, '\\x00'))\n  return argv.split(' ').map((arg: string) => {\n    arg = arg.replace(/\\0/g, ' ')\n    return removeQuotes(arg)\n  })\n}\n\nexport function parseCLI(argv: string | string[], config: CliParseOptions = {}): {\n  filter: string[]\n  options: CliOptions\n} {\n  const arrayArgs = typeof argv === 'string' ? splitArgv(argv) : argv\n  if (arrayArgs[0] !== 'vitest') {\n    throw new Error(`Expected \"vitest\" as the first argument, received \"${arrayArgs[0]}\"`)\n  }\n  arrayArgs[0] = '/index.js'\n  arrayArgs.unshift('node')\n  let { args, options } = createCLI(config).parse(arrayArgs, {\n    run: false,\n  })\n  if (arrayArgs[2] === 'watch' || arrayArgs[2] === 'dev') {\n    options.watch = true\n  }\n  if (arrayArgs[2] === 'run' && !options.watch) {\n    options.run = true\n  }\n  if (arrayArgs[2] === 'related') {\n    options.related = args\n    options.passWithNoTests ??= true\n    args = []\n  }\n  return {","sourceCodeStart":217,"sourceCodeEnd":253,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/vitest/src/node/cli/cac.ts#L217-L253","documentation":"Thrown by parseCLI() when the first element of the argv array is not the literal string \"vitest\". parseCLI is the internal entry that expects exactly the Vitest subcommand vector (starting with the program name \"vitest\"); it then rewrites argv[0] and prepends \"node\" for the cac parser. Any other first token means the caller passed the wrong argv shape.","triggerScenarios":"Calling parseCLI with the full `process.argv` (which starts with the node binary path), passing argv without the leading \"vitest\" token, or calling it from a wrapper that strips the program name. parseCLI is meant for the `vitest` CLI front-end only.","commonSituations":"Writing a custom CLI wrapper around Vitest and forwarding process.argv directly; integrating Vitest programmatically and mistakenly routing through parseCLI instead of the Vitest/Mocha API; a shell alias that invokes node with the script path.","solutions":["If using Vitest programmatically, prefer the `startVitest`/`Vitest` API or the `vitest node` entry instead of parseCLI.","If you must call parseCLI, ensure argv[0] === 'vitest' (e.g. parseCLI('vitest run')).","Do not pass raw process.argv; strip the node binary and script, then prepend 'vitest'."],"exampleFix":"// before\nparseCLI(process.argv)\n// after\nparseCLI(['vitest', 'run', 'src'])","handlingStrategy":"validation","validationCode":"const argv = typeof input === 'string' ? input : input\nconst arr = typeof argv === 'string' ? argv.split(' ') : argv\nif (arr[0] !== 'vitest') arr.unshift('vitest')\nparseCLI(arr)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer the public Vitest programmatic API (startVitest) over parseCLI.","If using parseCLI, always pass a vector whose first element is the literal 'vitest'.","Never forward raw process.argv to parseCLI."],"tags":[],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}