facebook/react · error
365
365
Error message
Invalid selector type specified.
What it means
matchSelector switches on selector.$$typeof and recognizes only the selector types the test-selector module defines (component, role, test name/ID, text, and the :has pseudo-class selector). Anything else falls into the default branch and throws (error code 365). In practice this means a hand-built selector object, a selector that lost its Symbol identity, or a selector created by a different React copy whose $$typeof symbols do not match the copy performing the match.
Source
Thrown at packages/react-reconciler/src/ReactTestSelectors.js:208
break;
case TEST_NAME_TYPE:
if (
tag === HostComponent ||
tag === HostHoistable ||
tag === HostSingleton
) {
const dataTestID = fiber.memoizedProps['data-testname'];
if (
typeof dataTestID === 'string' &&
dataTestID.toLowerCase() ===
(selector as any as TestNameSelector).value.toLowerCase()
) {
return true;
}
}
break;
default:
throw new Error('Invalid selector type specified.');
}
return false;
}
function selectorToString(selector: Selector): string | null {
switch (selector.$$typeof) {
case COMPONENT_TYPE:
const displayName = getComponentNameFromType(selector.value) || 'Unknown';
return `<${displayName}>`;
case HAS_PSEUDO_CLASS_TYPE:
return `:has(${selectorToString(selector) || ''})`;
case ROLE_TYPE:
return `[role="${(selector as any as RoleSelector).value}"]`;
case TEXT_TYPE:
return `"${(selector as any as TextSelector).value}"`;
case TEST_NAME_TYPE:
return `[data-testname="${(selector as any as TestNameSelector).value}"]`;View on GitHub (pinned to eafeac097b)
Solutions
- Build selectors only with the provided factories: createTestNameSelector, createComponentSelector, createRoleSelector, createTextSelector, createHasPseudoClassSelector
- Dedupe react so the creator and the matcher share one copy and its symbols (npm ls react)
- Never hand-write, cache across builds, or JSON-serialize selector objects — construct them at query time
Example fix
// before
findAllNodes(root, [{$$typeof: Symbol.for('react.test_name'), value: 'feed'}]); // hand-built
// after
import {createTestNameSelector} from 'react-reconciler'; // same React copy as the matcher
findAllNodes(root, [createTestNameSelector('feed')]); Defensive patterns
Strategy: type-guard
Validate before calling
// always construct selectors through the factories of the same React copy
import {createTestNameSelector} from '.../test-selectors';
const selectors = [createTestNameSelector('feed')];
findAllNodes(root, selectors); Type guard
const KNOWN_SELECTOR_TYPES = new Set([ COMPONENT_TYPE, ROLE_TYPE, TEST_NAME_TYPE, TEXT_TYPE, HAS_PSEUDO_CLASS_TYPE, ]); // import the TYPE constants from the same React copy that will match const isValidSelector = (s) => s != null && typeof s === 'object' && KNOWN_SELECTOR_TYPES.has(s.$$typeof);
Prevention
- Never hand-build selector objects or round-trip them through JSON (Symbols are lost)
- Dedupe react so selector creation and matching share one copy's symbols
- Build selectors at query time, not ahead of time across builds
When it happens
Trigger: Passing an object literal without a recognized $$typeof into findAllNodes/selector matching; passing selectors built by a second react/react-reconciler instance whose TEST_NAME_TYPE/ROLE_TYPE symbols differ from the one matching; selectors that survived JSON round-tripping (Symbols are lost).
Common situations: Duplicate react packages in a bundle where one builds the selector and another matches it; serialized test fixtures of selectors; hand-rolled selector objects copied from an older React version's shape.
Related errors
AI-assisted analysis of facebook/react@eafeac097b (2026-08-21).
Data as JSON: /api/errors/af60c40ddf2aa714.
Report an issue: GitHub.