{"record":{"id":"ded55a47d50872df","repo":"microsoft/playwright","slug":"unknown-engine-name-while-parsing-selector","errorCode":null,"errorMessage":"Unknown engine \"${name}\" while parsing selector ${stringifySelector(parsed)}","messagePattern":"Unknown engine \"(.+?)\" while parsing selector (.+?)","errorType":"exception","errorClass":"InvalidSelectorError","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/selectors.ts","lineNumber":84,"sourceCode":"    this._engines.set(engine.name, engine);\n  }\n\n  testIdAttributeName(): string {\n    return this._testIdAttributeName;\n  }\n\n  setTestIdAttributeName(testIdAttributeName: string) {\n    this._testIdAttributeName = testIdAttributeName;\n  }\n\n  parseSelector(selector: string | ParsedSelector, strict: boolean) {\n    const parsed = typeof selector === 'string' ? parseSelector(selector) : selector;\n    let needsMainWorld = false;\n    visitAllSelectorParts(parsed, part => {\n      const name = part.name;\n      const custom = this._engines.get(name);\n      if (!custom && !this._builtinEngines.has(name))\n        throw new InvalidSelectorError(`Unknown engine \"${name}\" while parsing selector ${stringifySelector(parsed)}`);\n      if (custom && !custom.contentScript)\n        needsMainWorld = true;\n      if (this._builtinEnginesInMainWorld.has(name))\n        needsMainWorld = true;\n    });\n    return {\n      parsed,\n      world: needsMainWorld ? 'main' as const : 'utility' as const,\n      strict,\n    };\n  }\n}\n","sourceCodeStart":66,"sourceCodeEnd":97,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/selectors.ts#L66-L97","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nawait page.locator('myEngine(div)').click();\n\n// after\nawait selectors.register({ name: 'myEngine', query: () => {...} });\nawait page.locator('myEngine(div)').click();","handlingStrategy":"validation","validationCode":"const BUILTIN = ['css','xpath','text','role','nth','visible','id','aria-ref'];\nfunction isKnownEngine(selectors: any, name: string): boolean {\n  return BUILTIN.includes(name) || name.startsWith('internal:') || selectors._engines.has(name);\n}\n\nconst engineName = selector.split(/[(:=]/)[0];\nif (!isKnownEngine(selectors, engineName))\n  throw new Error(`Unknown selector engine: ${engineName}. Register it first.`);","typeGuard":"function isResolvableSelector(selectors: any, selector: string): boolean {\n  try { selectors.parseSelector(selector, true); return true; }\n  catch { return false; }\n}","tryCatchPattern":"try {\n  await page.locator(selector).click();\n} catch (e) {\n  if (e instanceof Error && /Unknown engine/.test(e.message))\n    throw new Error(`Selector uses an unregistered engine: ${selector}`);\n  throw e;\n}","preventionTips":["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('."],"tags":["selectors","parse","invalid-selector","custom-engine"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}