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

  1. Resolve the Locator to an Element before passing it: use await locator.element() or await page.elementLocator(...).element().
  2. Ensure the value is a real Element via document.querySelector(...) and check for null before the matcher.
  3. If calling the adapter programmatically, guard with `value instanceof Element` before invoking capture().
  4. 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

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


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)