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
- Pass a single DOM Node (e.g. `document.querySelector('#x')`) or a Locator.
- Index into a collection first: `nodes[0]` rather than `nodes`.
- 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
- Pass a single Node (not a NodeList/HTMLCollection).
- Index collections before forwarding.
- Use Locators for selector-based lookups.
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
- received value must an HTMLElement or an SVGElement or a Loc
- toHaveFormValues must be called with an object of expected f
- Multiple form elements with the same name must be of the sam
- expected selection must be a string or undefined
- Element not found: ${v.element}
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/c93a81e078564eb4.
Report an issue: GitHub.