openclaw/openclaw · error · Error
Failed to open tab (non-selectable target)
Error message
Failed to open tab (non-selectable target)
What it means
Plain Error thrown at server-context.tab-ops.ts:433 when the freshly created CDP target fails isSelectableCdpBrowserTarget, i.e. created.type !== "page" OR the resolved URL (created.url ?? requested url) starts with a browser-internal scheme (chrome://, chrome-untrusted://, devtools://, edge://, brave://, vivaldi://, opera://). The runtime will not hand internal/devtools targets to user-facing automation.
Source
Thrown at extensions/browser/src/browser/server-context.tab-ops.ts:433
).catch(async (err: unknown) => {
if (String(err).includes("HTTP 405")) {
return await fetchJson<CdpTarget>(
endpoint,
cdpActionTimeouts?.httpTimeoutMs ?? CDP_JSON_NEW_TIMEOUT_MS,
undefined,
getCdpControlPolicy(),
);
}
throw err;
});
opts?.signal?.throwIfAborted();
if (!created.id) {
throw new Error("Failed to open tab (missing id)");
}
const resolvedUrl = created.url ?? url;
if (!isSelectableCdpBrowserTarget({ url: resolvedUrl, type: created.type })) {
throw new Error("Failed to open tab (non-selectable target)");
}
await assertBrowserNavigationResultAllowed({ url: resolvedUrl, ...ssrfPolicyOpts });
const wsUrl = normalizeWsUrl(created.webSocketDebuggerUrl, profile.cdpUrl);
const committedUrl = wsUrl
? await waitForCdpCommittedNavigationUrl({
wsUrl,
configuredCdpUrl: profile.cdpUrl,
cdpPolicy: getCdpControlPolicy(),
requestedUrl: url,
signal: opts?.signal,
timeouts: cdpActionTimeouts,
})
: undefined;
opts?.signal?.throwIfAborted();
if (!committedUrl) {
return await withTabOwnership(
{
targetId: created.id,View on GitHub (pinned to 01804a7531)
Solutions
- Open only real web URLs (http/https) or about:blank; do not pass chrome://, devtools://, or other internal schemes to openTab.
- If a redirect lands on an internal page, navigate to the final web URL directly instead of relying on the redirect.
- If you genuinely need an internal page, use the CDP target API directly rather than the selectable tab path — but most internal pages are intentionally non-selectable.
Example fix
// before
await openTab({ url: "chrome://settings" });
// after
await openTab({ url: "https://example.com" }); Defensive patterns
Strategy: validation
Validate before calling
import { isSelectableCdpBrowserTarget } from "./cdp-target-filter.js";
const INTERNAL = /^(chrome|chrome-untrusted|devtools|edge|brave|vivaldi|opera):\/\//i;
function isOpenableUrl(url) {
return /^https?:|^about:blank$/i.test(url) && !INTERNAL.test(url);
}
if (!isOpenableUrl(url)) {
// reject before calling openTab
} Type guard
function isOpenableTabUrl(url) {
return typeof url === "string" && /^(https?:|about:blank$)/i.test(url) &&
!/^(chrome|chrome-untrusted|devtools|edge|brave|vivaldi|opera):/i.test(url);
} Prevention
- Never pass chrome://, devtools://, or other internal schemes to openTab.
- Validate URLs at the agent/tool boundary before they reach the runtime.
- Treat non-page CDP target types as non-user-addressable.
When it happens
Trigger: Calling openTab with a chrome://, devtools://, or edge:// URL; or the CDP /json/new response yields a target whose type is not "page" (e.g. "background_page", "service_worker", "browser"). resolvedUrl falls back to the requested url when created.url is absent, so passing an internal scheme directly triggers it.
Common situations: A user/agent tries to open chrome://settings or devtools:// to automate browser config; a URL shortener/redirect lands on a browser-internal page; opening a URL that Chrome resolves to a non-page target type. Also seen when the requested url is empty and Chrome creates a service-worker target.
Related errors
- Failed to open tab (missing id)
- CDP /json/version returned non-object JSON
- Profile "${profile.name}" is remote; cannot launch local Chr
- Browser profile "${profile.name}" cannot launch: ${err insta
- OpenClaw Chrome extension is not connected to the relay
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/4df731361cb6beb7.
Report an issue: GitHub.