{"id":"baa9050b9183478b","repo":"vitest-dev/vitest","slug":"invalid-command-name-name-only-alphanumeric","errorCode":null,"errorMessage":"Invalid command name \"${name}\". Only alphanumeric characters, $ and _ are allowed.","messagePattern":"Invalid command name \"(.+?)\"\\. Only alphanumeric characters, \\$ and _ are allowed\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/node/project.ts","lineNumber":71,"sourceCode":"    }\n    this.testerFilepath = testerHtmlPath\n    this.testerHtml = readFile(\n      this.testerFilepath,\n      'utf8',\n    ).then(html => (this.testerHtml = html))\n  }\n\n  private commands = {} as Record<string, BrowserCommand<any, any>>\n\n  public registerCommand<K extends keyof BrowserCommands>(\n    name: K,\n    cb: BrowserCommand<\n      Parameters<BrowserCommands[K]>,\n      ReturnType<BrowserCommands[K]>\n    >,\n  ): void {\n    if (!/^[a-z_$][\\w$]*$/i.test(name)) {\n      throw new Error(\n        `Invalid command name \"${name}\". Only alphanumeric characters, $ and _ are allowed.`,\n      )\n    }\n    this.commands[name] = cb\n  }\n\n  public triggerCommand = (<K extends keyof BrowserCommand>(\n    name: K,\n    context: BrowserCommandContext,\n    ...args: Parameters<BrowserCommands[K]>\n  ): ReturnType<BrowserCommands[K]> => {\n    if (name in this.commands) {\n      return this.commands[name](context, ...args)\n    }\n    if (name in this.parent.commands) {\n      return this.parent.commands[name](context, ...args)\n    }\n    throw new Error(`Provider ${this.provider.name} does not support command \"${name}\".`)","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/vitest-dev/vitest/blob/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/node/project.ts#L53-L89","documentation":"`ProjectBrowser.registerCommand` validates the command name with `/^[a-z_$][\\w$]*$/i` (a valid JS identifier). Because commands are exposed in the generated context module as object keys called like functions, hyphens, dots, spaces, or leading digits break the generated code — so registration is rejected up front.","triggerScenarios":"Calling `project.browser.registerCommand('my-command', fn)` or `registerCommand('123name', fn)` with a name that isn't a valid identifier.","commonSituations":"User-defined commands registered via `browser.commands` in config with kebab-case keys; programmatic registration from a plugin using a dotted or dashed name.","solutions":["Rename the command to a valid identifier — camelCase or snake_case: `'myCommand'` or `'my_command'`.","If the name comes from `browser.commands` config keys, change them in the config (also see error 68).","Add a unit test for custom commands to catch invalid names before runtime."],"exampleFix":"// before\nproject.browser.registerCommand('upload-file', fn)\n\n// after\nproject.browser.registerCommand('uploadFile', fn)","handlingStrategy":"validation","validationCode":"function isValidCommandName(name: string): boolean {\n  return /^[a-z_$][\\w$]*$/i.test(name)\n}","typeGuard":"const isValidCommandName = (name: string): name is string =>\n  /^[a-z_$][\\w$]*$/i.test(name)","tryCatchPattern":null,"preventionTips":["Use camelCase or snake_case for command names; never kebab-case or dotted names.","Validate names in a unit test for any plugin that registers commands.","Remember the same regex applies to user-defined commands in config (error 68)."],"tags":["validation","browser-command","configuration"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}