{"record":{"id":"aaaafe3d7466c435","repo":"microsoft/playwright","slug":"selector-selector-does-not-match-any-element","errorCode":null,"errorMessage":"Selector \"${selector}\" does not match any element","messagePattern":"Selector \"(.+?)\" does not match any element","errorType":"exception","errorClass":"NonRecoverableDOMError","httpStatus":null,"severity":"error","filePath":"packages/playwright-core/src/server/page.ts","lineNumber":1131,"sourceCode":"}\n\nexport async function ariaSnapshotJSONForFrame(progress: Progress, frame: frames.Frame, selector: string | undefined, options: { mode?: 'ai' | 'default', doNotRenderActive?: boolean, depth?: number, boxes?: boolean, strict?: boolean, noDefaultPierce?: boolean } = {}): Promise<AriaSnapshotJSON> {\n  const snapshot = await frame.retryWithProgressAndTimeouts(progress, [1000, 2000, 4000, 8000], async (progress, continuePolling) => {\n    try {\n      // Note: the resolved frame might differ from the original |frame|.\n      // See https://developer.mozilla.org/en-US/docs/Web/API/Document/body for body/frameset explanation.\n      // Non-strict, because pages with nested framesets have multiple \"frameset\" elements.\n      const resolved = await progress.race(frame.selectors.callOnSelector(selector || 'body,frameset', { strict: options.strict ?? !!selector, noDefaultPierce: !selector || options.noDefaultPierce }, ({ injected, elements }, ariaOptions) => {\n        return injected.ariaSnapshotJSON(elements[0], ariaOptions);\n      }, {\n        mode: options.mode ?? 'default',\n        doNotRenderActive: options.doNotRenderActive,\n        depth: options.depth,\n        boxes: options.boxes,\n      }));\n      if (!resolved) {\n        if (selector)\n          throw new NonRecoverableDOMError(`Selector \"${selector}\" does not match any element`);\n        // Retry only for the main frame \"body\" being absent, so that `page.ariaSnapshotJSON()` does not fail.\n        return continuePolling;\n      }\n      return { ...resolved.result, resolvedFrame: resolved.frame };\n    } catch (e) {\n      if (frame.isNonRetriableError(e))\n        throw e;\n      return continuePolling;\n    }\n  });\n\n  // Only fetch child snapshots for iframes that were actually rendered (not filtered by depth).\n  const renderedIframeRefs = snapshot.iframeRefs.filter(ref => ref in snapshot.iframeDepths);\n  progress.setAllowConcurrentOrNestedRaces(true);\n  const childSnapshotPromises = renderedIframeRefs.map(async ref => {\n    const childDepth = options.depth ? options.depth - snapshot.iframeDepths[ref] - 1 : undefined;\n    // Non-strict, because child frameset documents have multiple \"frameset\" elements.\n    const frameRootSelector = `aria-ref=${ref} >> internal:control=enter-frame >> body,frameset`;","sourceCodeStart":1113,"sourceCodeEnd":1149,"githubUrl":"https://github.com/microsoft/playwright/blob/c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6/packages/playwright-core/src/server/page.ts#L1113-L1149","documentation":"Thrown by ariaSnapshotJSONForFrame when an explicit selector is passed to ariaSnapshotJSON but callOnSelector resolves to no element. With no selector the function falls back to body/frameset and retries, but when the caller supplies a selector and it matches nothing, the failure is non-recoverable (NonRecoverableDOMError) and stops retrying.","triggerScenarios":"Calling page.ariaSnapshotJSON() or locator.ariaSnapshotJSON() (with a selector) on an element that does not exist in the DOM; passing a selector before the element has rendered; a typo or stale selector after navigation.","commonSituations":"Capturing an aria snapshot for AI/assertions against a selector whose element is conditionally rendered; calling the snapshot too early before SPA hydration; selector regression after a UI refactor.","solutions":["Wait for the element to be present (await page.locator(sel).waitFor()) before calling ariaSnapshotJSON with that selector.","Verify the selector is correct against the current DOM (e.g. via page.locator(sel).count()).","If you want a whole-page snapshot, omit the selector so the body/frameset fallback with retries applies."],"exampleFix":"// before\nconst snap = await page.ariaSnapshotJSON({ /* via locator */ }); // selector matches nothing\n// after\nconst loc = page.locator('#dashboard');\nawait loc.waitFor();\nconst snap = await loc.ariaSnapshotJSON();","handlingStrategy":"validation","validationCode":"const loc = page.locator(selector);\nif (await loc.count() === 0)\n  throw new Error(`selector matches nothing: ${selector}`);\nawait loc.ariaSnapshotJSON();","typeGuard":null,"tryCatchPattern":"try {\n  await locator.ariaSnapshotJSON();\n} catch (e) {\n  if (/does not match any element/.test(e.message)) {\n    await locator.waitFor({ state: 'attached' });\n    // retry once, or fall back to page-level snapshot\n  } else throw e;\n}","preventionTips":["Wait for the element to be attached before snapshotting by selector.","Omit the selector for whole-page snapshots to use the body/frameset retry fallback.","Validate selectors after UI refactors."],"tags":["aria-snapshot","selector","dom","locator"],"backgroundTag":null,"analyzedSha":"c8fc3bf8d31542d59b4d4d9eaab1df93ff541dc6","analyzedAt":"2026-08-12T07:26:36.950Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}