{"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/d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09/packages/browser/src/client/tester/expect-element.ts#L1-L34","documentation":"Thrown by the element() helper used by expect.element() (packages/browser/src/client/tester/expect-element.ts:14-17) when the argument is non-null but is not an HTMLElement, an SVGElement, or a Locator (detected by the Symbol.for('$$vitest:locator') marker). expect.element is the entry point for DOM matchers like toHaveText, toBeVisible, toBeInTheDocument, so a wrong type fails fast before polling begins.","triggerScenarios":"Calling expect.element(value) where value is a string selector, a plain object, a number, a NodeList, or a component wrapper that doesn't expose the locator symbol. Common with expect.element(locator.findAll()) (returns array) instead of a single locator.","commonSituations":"Mixing testing-library queries (return elements) with Vitest Locator API; passing a CSS selector string instead of a locator; wrapping a locator in another object.","solutions":["Pass a single Element or a Vitest Locator: expect.element(page.getByText('Hi')) or expect.element(node).","If you have an array of locators, index first: expect.element(locators[0]).","For raw selectors, build a locator first: expect.element(page.locator('.btn'))."],"exampleFix":"// before\nexpect.element('.save-button').toHaveText('Save')\n// after\nexpect.element(page.locator('.save-button')).toHaveText('Save')","handlingStrategy":"type-guard","validationCode":"import type { Locator } from 'vitest/browser'\nconst kLocator = Symbol.for('$$vitest:locator')\nfunction isExpectableElement(v: unknown): v is HTMLElement | SVGElement | Locator {\n  return v == null\n    || v instanceof HTMLElement\n    || v instanceof SVGElement\n    || (v != null && typeof v === 'object' && kLocator in (v as object))\n}\nif (isExpectableElement(target)) {\n  expect.element(target as any)\n}","typeGuard":"function isElementOrLocator(v: unknown): v is HTMLElement | SVGElement | Locator {\n  if (v == null) return true\n  if (v instanceof HTMLElement || v instanceof SVGElement) return true\n  return typeof v === 'object' && Symbol.for('$$vitest:locator') in (v as object)\n}","tryCatchPattern":null,"preventionTips":["Only pass HTMLElement, SVGElement, or a Vitest Locator to expect.element.","Index locator arrays before asserting: expect.element(locators[0])."],"tags":["browser","expect","locators","type-error","expect-element"],"analyzedSha":"d568f8ce3739b532d5bf2c1ee1e45e8a8a473d09","analyzedAt":"2026-08-03T20:23:56.861Z","schemaVersion":2}