can1357/oh-my-pi · error · ToolError

Playwright-only selector ${JSON.stringify(selector)} is not

Error message

Playwright-only selector ${JSON.stringify(selector)} is not supported by the browser tool. Use a puppeteer text selector ("text/Allow all"), an aria selector ("aria/Name"), CSS, or "xpath/...".

What it means

The browser tool only accepts puppeteer-compatible selectors: CSS, or query-handler prefixed selectors (`aria/`, `text/`, `xpath/`, `pierce/`, plus legacy prefixes). If a selector matches none of the supported prefixes but looks like a Playwright-specific syntax (e.g. `role=button[name="x"]`, `:has-text(...)`, `::-p-text(...)`), normalizeSelector rejects it with this message.

Source

Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:284

		selector: string,
		opts?: { timeout?: number; visible?: boolean; hidden?: boolean },
	): Promise<ActionableHandle | null>;
	waitForNavigation(opts?: {
		waitUntil?: "load" | "domcontentloaded" | "networkidle0" | "networkidle2";
		timeout?: number;
	}): Promise<HTTPResponse | null>;
	id(n: number): Promise<ActionableHandle>;
	ref(id: string): Promise<ActionableHandle>;
}

export function normalizeSelector(selector: string): string {
	assertSelectorString(selector);
	if (!selector) return selector;
	if (
		!SELECTOR_HANDLER_PREFIXES.some(prefix => selector.startsWith(prefix)) &&
		PLAYWRIGHT_ONLY_SELECTOR_RE.test(selector)
	) {
		throw new ToolError(
			`Playwright-only selector ${JSON.stringify(selector)} is not supported by the browser tool. ` +
				`Use a puppeteer text selector ("text/Allow all"), an aria selector ("aria/Name"), CSS, or "xpath/...".`,
		);
	}
	if (selector.startsWith("p-") && !LEGACY_SELECTOR_PREFIXES.some(prefix => selector.startsWith(prefix))) {
		throw new ToolError(
			`Unsupported selector prefix. Use CSS or puppeteer query handlers (aria/, text/, xpath/, pierce/). Got: ${selector}`,
		);
	}
	if (selector.startsWith("p-text/")) return `text/${selector.slice("p-text/".length)}`;
	if (selector.startsWith("p-xpath/")) return `xpath/${selector.slice("p-xpath/".length)}`;
	if (selector.startsWith("p-pierce/")) return `pierce/${selector.slice("p-pierce/".length)}`;
	if (selector.startsWith("p-aria/")) {
		const rest = selector.slice("p-aria/".length);
		const nameMatch = rest.match(/\[\s*name\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\]]+))\s*\]/);
		const name = nameMatch?.[1] ?? nameMatch?.[2] ?? nameMatch?.[3];
		if (name) return `aria/${name.trim()}`;
		return `aria/${rest}`;

View on GitHub (pinned to 9690622007)

Solutions

  1. Convert Playwright role selectors to the aria handler: `role=button[name="Submit"]` → `aria/Submit`.
  2. Convert Playwright text selectors: `text=Allow all` or `:has-text(...)` → `text/Allow all`.
  3. Use plain CSS for structural matches, or `xpath/...` for XPath expressions.
  4. If using legacy `p-` prefixed handlers, migrate to the unprefixed forms (`p-text/` → `text/`); bare `p-` selectors now throw.

Example fix

// before
tab.click('button:has-text("Allow all")');
// after
tab.click('text/Allow all');
Defensive patterns

Strategy: validation

Validate before calling

const PLAYWRIGHT_ONLY = /(role=|:has-text\(|:left-of\(|:right-of\(|:near\(|::-p-)/;
if (PLAYWRIGHT_ONLY.test(selector)) {
  throw new Error(`convert Playwright selector to aria/, text/, CSS, or xpath/: ${selector}`);
}

Type guard

function isSupportedSelector(s: string): boolean {
  return !/(role=|:has-text\(|::-p-)/.test(s);
}

Prevention

When it happens

Trigger: Passing a Playwright locator string to tab.click/handles/fill/etc., e.g. `page.getByRole(...)` strings like `role=button[name="Submit"]`, or selectors using Playwright pseudo-classes like `:has-text("...")`, `:right-of(...)`, or `text="exact"` without the `text/` prefix.

Common situations: Developers porting Playwright scripts or copy-pasting selectors from Playwright codegen/examples into the browser tool; LLM-generated selectors using Playwright conventions.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1abe984c584bd589. Report an issue: GitHub.