vitest-dev/vitest · error · Error
Expected element or locator to be an instance of Element or
Error message
Expected element or locator to be an instance of Element or Locator.
What it means
Thrown by `serializeElement` at tester-utils.ts:310 when the input is truthy but is neither an `instanceof Element` nor passes the `isLocator` duck-type check (Symbol.for('$$vitest:locator') in object). The serializer only accepts real DOM Elements or Vitest Locators.
Source
Thrown at packages/browser/src/client/tester/tester-utils.ts:310
export async function serializeElement(elementOrLocator: Element | Locator, options?: SelectorOptions): Promise<SerializedLocator> {
if (!elementOrLocator) {
throw new Error('Expected element or locator to be defined.')
}
if (elementOrLocator instanceof Element) {
const selector = convertElementToCssSelector(elementOrLocator)
return { selector, locator: __INTERNAL._asLocator('javascript', selector) }
}
if (isLocator(elementOrLocator)) {
if (provider === 'playwright' || kElementLocator in elementOrLocator) {
return elementOrLocator.serialize()
}
const element = await elementOrLocator.findElement(options)
const selector = convertElementToCssSelector(element)
const locator = __INTERNAL._asLocator('javascript', selector)
return { selector, locator }
}
throw new Error('Expected element or locator to be an instance of Element or Locator.')
}
const kLocator = Symbol.for('$$vitest:locator')
export function isLocator(element: unknown): element is Locator {
return (!!element && typeof element === 'object' && kLocator in element)
}
const DEFAULT_WHEEL_DELTA = 100
export function resolveUserEventWheelOptions(options: UserEventWheelOptions): UserEventWheelDeltaOptions {
let delta: UserEventWheelDeltaOptions['delta']
if (options.delta) {
delta = options.delta
}
else {
switch (options.direction) {View on GitHub (pinned to d568f8ce37)
Solutions
- Pass a DOM Element obtained via `querySelector`/`getByRole` etc., or a Vitest `Locator`.
- Unwrap collections/jQuery: pass `$(sel)[0]` not `$(sel)`.
- If using a custom locator abstraction, adapt it to expose the Vitest Locator interface or resolve to an Element first.
Example fix
// before
await serializeElement($('.btn')) // jQuery wrapper
// after
await serializeElement(document.querySelector('.btn')!) Defensive patterns
Strategy: type-guard
Validate before calling
import { isLocator } from '@vitest/browser/client'
function isSerializable(v: unknown): v is Element | Locator {
return v instanceof Element || isLocator(v)
}
if (!isSerializable(target)) throw new Error('expected Element or Locator') Type guard
function isElementOrLocator(v: unknown): v is Element | Locator {
const kLocator = Symbol.for('$$vitest:locator')
return v instanceof Element || (!!v && typeof v === 'object' && kLocator in v)
} Prevention
- Pass DOM Elements or Vitest Locators; never plain objects, strings, or jQuery wrappers.
- Unwrap collections to a single Element.
- Adapt custom locator abstractions to expose the Vitest Locator interface.
When it happens
Trigger: Passing a plain object, a string, a number, a Node that isn't an Element (text/comment node), a Playwright Locator from a different library, or a stale wrapper that lost its symbol.
Common situations: Hand-constructing a locator-like object. Passing a jQuery wrapper or testing-library element instead of a DOM Element. Cross-realm Element instances failing `instanceof Element` (rare; usually caught earlier).
Related errors
- Expected DOM element to be an instance of Element, received
- Expected element or locator to be defined.
- received value must ${expectedString} or a Locator that retu
- toHaveFormValues must be called on a form or a fieldset, ins
- Cannot take a screenshot without a test path
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/b15ccffa540eac02.json.
Report an issue: GitHub.