microsoft/playwright · error · InvalidSelectorError
Unknown engine "${name}" while parsing selector ${stringifyS
Error message
Unknown engine "${name}" while parsing selector ${stringifySelector(parsed)} What it means
Thrown as an InvalidSelectorError by Selectors.parseSelector when a selector string references an engine name that is neither a builtin (_builtinEngines) nor a custom engine previously registered via register(). Visit-all-selector-parts encounters the unknown prefix and aborts parsing before any lookup runs.
Source
Thrown at packages/playwright-core/src/server/selectors.ts:84
this._engines.set(engine.name, engine);
}
testIdAttributeName(): string {
return this._testIdAttributeName;
}
setTestIdAttributeName(testIdAttributeName: string) {
this._testIdAttributeName = testIdAttributeName;
}
parseSelector(selector: string | ParsedSelector, strict: boolean) {
const parsed = typeof selector === 'string' ? parseSelector(selector) : selector;
let needsMainWorld = false;
visitAllSelectorParts(parsed, part => {
const name = part.name;
const custom = this._engines.get(name);
if (!custom && !this._builtinEngines.has(name))
throw new InvalidSelectorError(`Unknown engine "${name}" while parsing selector ${stringifySelector(parsed)}`);
if (custom && !custom.contentScript)
needsMainWorld = true;
if (this._builtinEnginesInMainWorld.has(name))
needsMainWorld = true;
});
return {
parsed,
world: needsMainWorld ? 'main' as const : 'utility' as const,
strict,
};
}
}
View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Register the custom engine on the same Selectors instance/context before using it in selectors.
- Correct the typo — use a builtin name (css, xpath, text, role, etc.) if that was intended.
- Ensure the engine is registered once at startup, before any page.querySelector/locator call uses it.
Example fix
// before
await page.locator('myEngine(div)').click();
// after
await selectors.register({ name: 'myEngine', query: () => {...} });
await page.locator('myEngine(div)').click(); Defensive patterns
Strategy: validation
Validate before calling
const BUILTIN = ['css','xpath','text','role','nth','visible','id','aria-ref'];
function isKnownEngine(selectors: any, name: string): boolean {
return BUILTIN.includes(name) || name.startsWith('internal:') || selectors._engines.has(name);
}
const engineName = selector.split(/[(:=]/)[0];
if (!isKnownEngine(selectors, engineName))
throw new Error(`Unknown selector engine: ${engineName}. Register it first.`); Type guard
function isResolvableSelector(selectors: any, selector: string): boolean {
try { selectors.parseSelector(selector, true); return true; }
catch { return false; }
} Try / catch
try {
await page.locator(selector).click();
} catch (e) {
if (e instanceof Error && /Unknown engine/.test(e.message))
throw new Error(`Selector uses an unregistered engine: ${selector}`);
throw e;
} Prevention
- Register all custom engines on the context before any selector that uses them is evaluated.
- Use only builtin engine prefixes unless a custom engine has been registered.
- Lint selector strings at build time to catch typos like 'roll(' instead of 'role('.
When it happens
Trigger: Using a selector like 'myEngine(div)' or 'prefix=foo' where 'myEngine'/'prefix' was never registered; a typo in a builtin name ('role' vs 'roll'); referencing a custom engine registered in a different Selectors instance.
Common situations: Forgetting to call selectors.register before using the engine in a selector; typo in an engine prefix; engine registered on a different browser context than the one running the query.
Related errors
- Selector engine name may only contain [a-zA-Z0-9_] character
- "${engine.name}" is a predefined selector engine
- "${engine.name}" selector engine has been already registered
- Unsupported token "${unsupportedToken.toSource()}" while par
- Error while parsing css selector "${selector}". Did you mean
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/ded55a47d50872df.
Report an issue: GitHub.