vitest-dev/vitest · error · Error

Expected DOM element to be an instance of Element, received

Error message

Expected DOM element to be an instance of Element, received ${typeof element}

What it means

Thrown by `convertElementToCssSelector` when its argument is falsy or not an `instanceof Element`. The function builds a unique CSS selector for a given DOM element so it can be serialized and re-resolved (e.g. sent to the browser command server); a non-Element cannot have a CSS path, so it is rejected with the received type name.

Solutions

  1. Ensure the value is a real DOM `Element` before calling (e.g. guard with `instanceof Element`).
  2. Resolve Locators to an element first and check for null.
  3. Prefer the public Locator/serializer API rather than calling `convertElementToCssSelector` directly.

Example fix

// before
convertElementToCssSelector(maybeNull)

// after
if (maybeNull instanceof Element) {
  convertElementToCssSelector(maybeNull)
}
Defensive patterns

Strategy: type-guard

Validate before calling

function assertElement(el: unknown): asserts el is Element {
  if (!(el instanceof Element)) {
    throw new TypeError(`Expected Element, got ${typeof el}`)
  }
}
assertElement(maybeEl)
convertElementToCssSelector(maybeEl)

Type guard

function isElement(el: unknown): el is Element {
  return !!el && el instanceof Element
}

Prevention

When it happens

Trigger: Passing `null`/`undefined`, a Locator that failed to resolve, a plain object, a string selector, or a Node that is not an Element (text/comment node) to `convertElementToCssSelector`.

Common situations: Internal callers that received an unresolved element; user code reaching an internal helper with a wrong value; a Locator whose `.element()` returned null being passed through.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/087526821f58d90e. Report an issue: GitHub.

Appendix: source

Thrown at packages/browser/src/client/tester/tester-utils.ts:11

import type { Locator, SelectorOptions, SerializedLocator, UserEventWheelDeltaOptions, UserEventWheelOptions } from 'vitest/browser'
import type { BrowserRPC } from '../client'
import type { BrowserTraceEntryStatus } from './trace'
import { __INTERNAL } from 'vitest/internal/browser'
import { getBrowserState, getWorkerState, now } from '../utils'
import { createBrowserTraceRangeId, recordBrowserTraceEntry } from './trace'

/* @__NO_SIDE_EFFECTS__ */
export function convertElementToCssSelector(element: Element): string {
  if (!element || !(element instanceof Element)) {
    throw new Error(
      `Expected DOM element to be an instance of Element, received ${typeof element}`,
    )
  }

  return getUniqueCssSelector(element)
}

function escapeIdForCSSSelector(id: string) {
  return id
    .split('')
    .map((char) => {
      const code = char.charCodeAt(0)

      if (char === ' ' || char === '#' || char === '.' || char === ':' || char === '[' || char === ']' || char === '>' || char === '+' || char === '~' || char === '\\') {
        // Escape common special characters with backslashes
        return `\\${char}`
      }
      else if (code >= 0x10000) {

View on GitHub (pinned to 1fa9837ec2)