facebook/flow · error · SyntaxError
Syntax error in selector "${rawSelector}" at position ${err.
Error message
Syntax error in selector "${rawSelector}" at position ${err.location.start.offset}: ${err.message} What it means
tryParseSelector() runs each selector string through esquery.parse() (after stripping a trailing :exit) and rethrows parse failures as a SyntaxError that includes the offset and the underlying esquery message. Selectors originate from the event names registered on your visitor — keys that are not visitXxx method names are treated as raw esquery strings. This error means one of those strings is not valid esquery syntax, for example an unbalanced bracket, a stray combinator, or a malformed pseudo-class.
Source
Thrown at packages/flow-transform/src/traverse/NodeEventGenerator.js:235
);
}
/**
* Parses a raw selector string, and throws a useful error if parsing fails.
* @param rawSelector A raw AST selector
* @returns An object (from esquery) describing the matching behavior of this selector
* @throws An error if the selector is invalid
*/
function tryParseSelector(rawSelector: string): Selector {
try {
return esquery.parse(rawSelector.replace(/:exit$/u, ''));
} catch (err) {
if (
err.location &&
err.location.start &&
typeof err.location.start.offset === 'number'
) {
throw new SyntaxError(
`Syntax error in selector "${rawSelector}" at position ${err.location.start.offset}: ${err.message}`,
);
}
throw err;
}
}
const selectorCache = new Map<string, ParsedSelector>();
/**
* Parses a raw selector string, and returns the parsed selector along with specificity and type information.
* @param rawSelector A raw AST selector
* @returns A selector descriptor
*/
function parseSelector(rawSelector: string): ParsedSelector {
const cachedSelector = selectorCache.get(rawSelector);
if (cachedSelector) {
return cachedSelector;View on GitHub (pinned to d1341dac89)
Solutions
- Fix the selector syntax per esquery grammar (balanced brackets, valid pseudo-classes, supported combinators); keep ':exit' as the exact suffix.
- Dry-run validation: call esquery.parse on each selector string during development/startup so failures surface with position before traversal.
- Prefix non-selector helper properties so they are not collected as event names, or keep them off the visitor object.
- Use simple type-name selectors (visitXxx) unless you need esquery complexity.
Example fix
// before
const visitor = {
visitCallExpression(node) {},
'CallExpression > ': fn, // trailing combinator -> SyntaxError
};
// after
const visitor = {
visitCallExpression(node) {},
'CallExpression > MemberExpression': fn, // valid esquery
}; Defensive patterns
Strategy: validation
Validate before calling
import esquery from 'esquery';
function validateSelectors(selectors) {
for (const raw of selectors) {
try {
esquery.parse(raw.replace(/:exit$/u, ''));
} catch {
throw new Error(`Invalid AST selector: ${JSON.stringify(raw)}`);
}
}
} Try / catch
try {
traverse(ast, visitor);
} catch (err) {
if (err instanceof SyntaxError && err.message.includes('Syntax error in selector')) {
// the message names the raw selector and offset; fix or drop that selector
console.error(err.message);
} else {
throw err;
}
} Prevention
- Dry-run esquery.parse on every string selector during development/startup.
- Keep non-visitor helper properties off the visitor object so they are not parsed as selectors.
- Prefer simple visitXxx keys; add complex esquery strings incrementally with tests.
When it happens
Trigger: Adding an arbitrary string key to the visitor object such as 'CallExpression >' , '[async=true' , or ':exitt' (misspelled exit pseudo); registering selector strings with unsupported esquery features; trailing whitespace or smart quotes pasted from docs.
Common situations: Using advanced esquery attribute/pseudo selectors and getting the syntax slightly wrong; typos in the ':exit' suffix; keys on the visitor object that were meant as helper methods but got parsed as selectors because they do not start with 'visit'.
Related errors
- No visitor keys found for node type "${node.type}".
- Unexpected selector ${parsedSelector.value}
- No visitor keys found for node type "${node.type}".
- Attempted to mutate a `${node.type}.${key}` on a deleted nod
- Attempted to mutate a `${node.type}.${key}` when it has alre
AI-assisted analysis of facebook/flow@d1341dac89 (2026-08-17).
Data as JSON: /api/errors/93c8429ae2b8d3e3.
Report an issue: GitHub.