vitest-dev/vitest · error · UserInputNodeTypeError

received value must a Node or a Locator that returns a Node.

Error message

received value must a Node or a Locator that returns a Node.

What it means

Thrown by `getNodeFromUserInput` (as `UserInputNodeTypeError`) when the value passed to a node-based matcher/function is not a DOM `Node` or a `Locator` resolving to one. The helper unwraps a `Locator` via `.element()` then checks `instanceof defaultView.Node`; text nodes, comment nodes, document fragments, and elements all pass, but non-Node values (string, number, plain object, Window) are rejected.

Source

Thrown at packages/browser/src/client/tester/expect/utils.ts:79

export function getNodeFromUserInput(
  elementOrLocator: Element | Locator,
  matcherFn: (...args: any) => any,
  context: MatcherState,
): Node {
  if (elementOrLocator instanceof Locator) {
    elementOrLocator = elementOrLocator.element()
  }

  const defaultView = elementOrLocator.ownerDocument?.defaultView || window

  if (
    elementOrLocator instanceof defaultView.Node
  ) {
    return elementOrLocator
  }

  throw new UserInputNodeTypeError(
    elementOrLocator,
    matcherFn,
    context,
  )
}

export function getMessage(
  context: MatcherState,
  matcher: string,
  expectedLabel: string,
  expectedValue: unknown,
  receivedLabel: string,
  receivedValue: unknown,
): string {
  return [
    `${matcher}\n`,

    `${expectedLabel}:\n${context.utils.EXPECTED_COLOR(

View on GitHub (pinned to 1fa9837ec2)

Solutions

  1. Pass a single DOM Node (e.g. `document.querySelector('#x')`) or a Locator.
  2. Index into a collection first: `nodes[0]` rather than `nodes`.
  3. For selector-based lookups, build a Locator with `page.locator(...)` / `getBy*` helpers.

Example fix

// before
expect(document.querySelectorAll('.item')).toHaveTextContent('x')

// after
expect(document.querySelector('.item')).toHaveTextContent('x')
Defensive patterns

Strategy: type-guard

Validate before calling

function isNodeOrLocator(v: unknown): v is Node | Locator {
  return v instanceof Node
    || (!!v && typeof v === 'object' && Symbol.for('$$vitest:locator') in (v as object))
}
if (!isNodeOrLocator(target)) throw new TypeError('pass a Node or Locator')

Type guard

function isNodeOrLocator(v: unknown): v is Node | Locator {
  return v instanceof Node
    || (!!v && typeof v === 'object' && Symbol.for('$$vitest:locator') in (v as object))
}

Prevention

When it happens

Trigger: Passing a selector string, a Window, a plain object, or null/undefined to a function that uses `getNodeFromUserInput`; passing a NodeList or HTMLCollection instead of a single Node.

Common situations: Treating a matcher as selector-based; passing a collection where a single node is required; cross-document nodes whose `defaultView` differs from the current window.

Related errors


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