vitest-dev/vitest · error · TypeError
aria adapter expects an Element
Error message
aria adapter expects an Element
What it means
The aria snapshot adapter's capture() method only accepts a DOM Element. Vitest throws this TypeError when the matcher backing toMatchAriaSnapshot receives something that is not an Element instance (e.g. a Locator, a Document, a plain object, or null). Internally generateAriaTree walks the DOM, so any non-Element input is rejected before tree generation begins.
Solutions
- Resolve the Locator to an Element before passing it: use await locator.element() or await page.elementLocator(...).element().
- Ensure the value is a real Element via document.querySelector(...) and check for null before the matcher.
- If calling the adapter programmatically, guard with `value instanceof Element` before invoking capture().
- Re-query the DOM if the node may have been detached since it was first obtained.
Example fix
// before expect(locator).toMatchAriaSnapshot(`- button "Save"`) // after expect(await locator.element()).toMatchAriaSnapshot(`- button "Save"`)
Defensive patterns
Strategy: type-guard
Validate before calling
if (!(value instanceof Element)) {
throw new Error('aria snapshot requires an Element')
}
expect(value).toMatchAriaSnapshot(template) Type guard
function isElement(value: unknown): value is Element {
return typeof Element !== 'undefined' && value instanceof Element
} Try / catch
try {
expect(await locator.element()).toMatchAriaSnapshot(template)
} catch (e) {
if (e instanceof TypeError && /aria adapter expects an Element/.test(e.message)) {
// resolve the locator and retry
} else throw e
} Prevention
- Always resolve Locators via await locator.element() before aria snapshot matchers.
- Type your helper inputs as Element rather than Element | Locator where possible.
- Add a runtime instanceof Element guard in shared assertion utilities.
When it happens
Trigger: Calling expect(locator).toMatchAriaSnapshot(...) where locator is a Vitest Locator that has not been resolved to an Element; passing document or window to an aria snapshot matcher; passing null/undefined to the aria adapter's capture; calling the aria adapter directly with a serialized/stale node reference.
Common situations: Using the aria snapshot API with a Locator object instead of resolving it via .element(); running in an environment where the DOM node was detached/removed before capture; passing the result of querySelector that returned null; SSR or jsdom contexts where Element is not the same constructor as the one in the captured node.
Related errors
- Expecting a valid DOM element, but got
- Invalid element or locator
- Element not found
- Expected DOM element to be an instance of Element, received
- Expected element or locator to be an instance of Element or…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/c33516232eb96767.
Report an issue: GitHub.
Appendix: source
Thrown at packages/browser/src/client/tester/aria.ts:31
getBrowserState().aria = aria
const {
generateAriaTree,
matchAriaTree,
parseAriaTemplate,
renderAriaTemplate,
renderAriaTree,
} = aria
const ariaSnapshotAdapter: DomainSnapshotAdapter<AriaNode, AriaTemplateNode> = {
name: 'aria',
capture(received) {
if (received instanceof Element) {
return generateAriaTree(received)
}
throw new TypeError('aria adapter expects an Element')
},
render(captured) {
return wrapNewlines(renderAriaTree(captured))
},
parseExpected(input) {
// increase limit so that yaml parse error can reach `toMatchAriaSnapshot` callsite in user test files
const limit = Error.stackTraceLimit
Error.stackTraceLimit = limit + 20
try {
return parseAriaTemplate(input.trim())
}
finally {
Error.stackTraceLimit = limit
}
},
View on GitHub (pinned to 1fa9837ec2)