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` at tester-utils.ts:10-14 when its argument is falsy or not an `instanceof Element`. This helper builds a unique CSS selector for an element so it can be shipped to the browser-driver (Playwright/WebDriver) for interaction; passing anything other than a real DOM Element makes selector generation impossible.
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 d568f8ce37)
Solutions
- Ensure the element exists in the DOM before resolving it; use `await page.locator(...).element()` or wait helpers.
- Unwrap refs/holders: pass `ref.current`, not the ref object.
- Add a null guard and fail with a clearer message if the element genuinely isn't present.
Example fix
// before
const el = document.querySelector('.maybe-gone')
convertElementToCssSelector(el) // el is null
// after
const el = document.querySelector('.maybe-gone')
if (!el) throw new Error('element missing')
convertElementToCssSelector(el) Defensive patterns
Strategy: type-guard
Validate before calling
function isElement(v: unknown): v is Element {
return v instanceof Element
}
if (!isElement(target)) throw new Error('target is not a DOM Element') Type guard
function isElement(v: unknown): v is Element {
return v instanceof Element
} Prevention
- Resolve elements with querySelector/locator.element() and guard for null.
- Unwrap framework refs (ref.current) before passing.
- Use waitFor/locator waits to ensure presence before resolution.
When it happens
Trigger: Passing `null`/`undefined`, a text node, a Locator whose `.element()` returned null, a Window, or a serialized element stub. Triggered indirectly by locators and user-event utilities that ultimately call `convertElementToCssSelector`.
Common situations: A Locator resolved to nothing because the element wasn't in the DOM yet (timing). Selecting via `querySelector` that returned null and not guarding. Passing a React/Vue ref wrapper object instead of `.current`.
Related errors
- Expected element or locator to be an instance of Element or
- received value must ${expectedString} or a Locator that retu
- Expected element or locator to be defined.
- toHaveFormValues must be called on a form or a fieldset, ins
- Element not found: ${v.element}
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/087526821f58d90e.json.
Report an issue: GitHub.