microsoft/playwright · error · Error
"${engine.name}" is a predefined selector engine
Error message
"${engine.name}" is a predefined selector engine What it means
Thrown by Selectors.register when the engine name collides with a predefined/builtin engine. The check covers everything in _builtinEngines (css, xpath, text, role, internal:*, data-testid variants, etc.) plus the reserved names 'zs' and 'zs:light' kept for future use. Registering over a builtin would break core selector resolution, so it is rejected outright.
Source
Thrown at packages/playwright-core/src/server/selectors.ts:63
'role', 'internal:attr', 'internal:label', 'internal:text',
'internal:role', 'internal:testid', 'internal:describe',
'aria-ref'
]);
this._builtinEnginesInMainWorld = new Set([
'_react', '_vue',
]);
this._engines = new Map();
this._testIdAttributeName = testIdAttributeName ?? 'data-testid';
for (const engine of engines)
this.register(engine);
}
register(engine: channels.SelectorEngine) {
if (!engine.name.match(/^[a-zA-Z_0-9-]+$/))
throw new Error('Selector engine name may only contain [a-zA-Z0-9_] characters');
// Note: we keep 'zs' for future use.
if (this._builtinEngines.has(engine.name) || engine.name === 'zs' || engine.name === 'zs:light')
throw new Error(`"${engine.name}" is a predefined selector engine`);
if (this._engines.has(engine.name))
throw new Error(`"${engine.name}" selector engine has been already registered`);
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;View on GitHub (pinned to c8fc3bf8d3)
Solutions
- Choose a non-builtin, non-reserved name for your custom engine.
- If you intended to extend a builtin, register a new engine with a distinct name and use that engine prefix in your selectors.
- Check the _builtinEngines list in the source before naming your engine.
Example fix
// before
selectors.register({ name: 'text', query: () => {...} });
// after
selectors.register({ name: 'my-text', query: () => {...} }); Defensive patterns
Strategy: validation
Validate before calling
const BUILTIN_ENGINES = new Set([
'css','css:light','xpath','xpath:light','_react','_vue',
'text','text:light','id','id:light','role','nth','visible',
'internal:control','internal:has','internal:has-not','internal:has-text',
'internal:has-not-text','internal:and','internal:or','internal:chain',
'internal:attr','internal:label','internal:text','internal:role',
'internal:testid','internal:describe','aria-ref','zs','zs:light'
]);
if (BUILTIN_ENGINES.has(name)) throw new Error(`${name} is a builtin engine`); Type guard
function isBuiltinEngine(name: string): boolean {
const builtins = ['css','xpath','text','role','nth','visible','id','aria-ref','zs','zs:light'];
return builtins.includes(name) || name.startsWith('internal:') || name.endsWith(':light');
} Prevention
- Namespace custom engine names with a unique prefix unlikely to collide with builtins.
- Cross-check a candidate name against the builtin list in selectors.ts before registering.
- Avoid overriding builtin engines; extend functionality under a new name instead.
When it happens
Trigger: Calling selectors.register with a name like 'css', 'xpath', 'text', 'role', 'internal:has', 'data-testid', or the reserved 'zs'/'zs:light'.
Common situations: Unaware that a name is builtin; dynamically generating engine names without checking the builtin set; trying to override the text/role engine behavior.
Related errors
- Selector engine name may only contain [a-zA-Z0-9_] character
- "${engine.name}" selector engine has been already registered
- Unknown engine "${name}" while parsing selector ${stringifyS
AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12).
Data as JSON: /api/errors/037c990b439acb9f.
Report an issue: GitHub.