{"record":{"id":"646f8d5bf7ce2ca4","repo":"vitest-dev/vitest","slug":"invalid-element-or-locator-elementorlocator-e","errorCode":null,"errorMessage":"Invalid element or locator: ${elementOrLocator}. Expected an instance of HTMLElement, SVGElement or Locator, received ${getType(elementOrLocator)}","messagePattern":"Invalid element or locator: (.+?)\\. Expected an instance of HTMLElement, SVGElement or Locator, received (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/browser/src/client/tester/expect-element.ts","lineNumber":16,"sourceCode":"import type { Assertion, ExpectPollOptions } from 'vitest'\nimport type { Locator } from 'vitest/browser'\nimport type { BrowserTraceEntryStatus } from './trace'\nimport { chai, expect } from 'vitest'\nimport { getType } from 'vitest/internal/browser'\nimport { getBrowserState, getWorkerState, now } from '../utils'\nimport { ariaMatchers } from './aria'\nimport { matchers } from './expect'\nimport { processTimeoutOptions } from './tester-utils'\nimport { createBrowserTraceRangeId, recordBrowserTraceEntry } from './trace'\n\nconst kLocator = Symbol.for('$$vitest:locator')\n\nfunction element<T extends HTMLElement | SVGElement | null | Locator>(elementOrLocator: T, options?: ExpectPollOptions): Assertion<Promise<void>, HTMLElement | SVGElement | null> {\n  if (elementOrLocator != null && !(elementOrLocator instanceof HTMLElement) && !(elementOrLocator instanceof SVGElement) && !(kLocator in elementOrLocator)) {\n    throw new Error(`Invalid element or locator: ${elementOrLocator}. Expected an instance of HTMLElement, SVGElement or Locator, received ${getType(elementOrLocator)}`)\n  }\n\n  const pollOptions = processTimeoutOptions(options)\n  const deadline = pollOptions?.timeout ? now() + pollOptions.timeout : undefined\n  const expectElement = expect.poll(async function element(this: object): Promise<HTMLElement | SVGElement | null> {\n    if (elementOrLocator instanceof Element || elementOrLocator == null) {\n      return elementOrLocator\n    }\n\n    const isNot = chai.util.flag(this, 'negate') as boolean\n    const name = chai.util.flag(this, '_name') as string\n    // special case for `toBeInTheDocument` matcher\n    if (isNot && name === 'toBeInTheDocument') {\n      return elementOrLocator.query()\n    }\n    if (name === 'toHaveLength') {\n      // we know that `toHaveLength` requires multiple elements,\n      // but types generally expect a single one","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/vitest-dev/vitest/blob/1fa9837ec26533512fdcad8baebf249771bd340a/packages/browser/src/client/tester/expect-element.ts#L1-L34","documentation":"expect.element() (the entry point for element assertions like expect(el).toBeVisible()) validates its argument up front: it must be null, undefined, an HTMLElement, an SVGElement, or an object carrying the internal Locator symbol ($$vitest:locator). Anything else throws immediately with the received type name. This guards the polling wrapper from receiving a value it cannot resolve to a DOM node.","triggerScenarios":"Calling expect(myString).toBeVisible(); passing a number, plain object, NodeList, or a third-party Locator-like object that lacks the $$vitest:locator symbol; passing a Promise that was not awaited.","commonSituations":"Mixing Vitest Locators with Playwright/RTL locators; forgetting to await an async query; passing the result of a querySelector without null-checking when it actually returned a non-Element (e.g. due to a wrapper).","solutions":["Pass only HTMLElement/SVGElement (or null) or a Vitest Locator produced by page.getByRole/getByText etc.","Await async lookups before passing: const el = await locator.element().","If integrating a third-party locator, convert it to a Vitest Locator via page.elementLocator on its underlying Element."],"exampleFix":"// before\nexpect(document.querySelectorAll('.btn')).toBeVisible()  // NodeList\n// after\nexpect(document.querySelector('.btn')).toBeVisible()","handlingStrategy":"type-guard","validationCode":"const kLocator = Symbol.for('$$vitest:locator')\nfunction isValidTarget(v: unknown): boolean {\n  return v == null || v instanceof HTMLElement || v instanceof SVGElement || (typeof v === 'object' && v !== null && kLocator in v)\n}\nif (!isValidTarget(el)) throw new Error('invalid target')\nexpect(el).toBeVisible()","typeGuard":"function isElementOrLocator(v: unknown): v is HTMLElement | SVGElement | Locator {\n  const kLocator = Symbol.for('$$vitest:locator')\n  return v instanceof HTMLElement || v instanceof SVGElement || (typeof v === 'object' && v !== null && kLocator in v)\n}","tryCatchPattern":null,"preventionTips":["Pass only HTMLElement/SVGElement, null, or a Vitest Locator to expect.element-based assertions.","Await async lookups before passing their result.","Convert third-party locators to Vitest Locators via page.elementLocator."],"tags":["browser","expect","locator","type-guard","dom"],"backgroundTag":null,"analyzedSha":"1fa9837ec26533512fdcad8baebf249771bd340a","analyzedAt":"2026-08-11T16:11:39.638Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}