openclaw/openclaw · error · BrowserTargetAmbiguousError
ambiguous browser tab reference
Error message
ambiguous browser tab reference
What it means
Thrown by BrowserTargetAmbiguousError (HTTP 409) in the listTabs default-selection path when resolveById returns the sentinel 'AMBIGUOUS'. This happens when a non-exact tab reference (label or alias) matches more than one candidate tab. The default error message is 'ambiguous browser tab reference'.
Source
Thrown at extensions/browser/src/browser/server-context.selection.ts:217
const last = stickyTargetId ?? "";
const lastResolved = last ? resolveById(last, { exactTargetId: true }) : null;
if (lastResolved && lastResolved !== "AMBIGUOUS") {
return lastResolved;
}
// Sticky selection is an identity promise. If it disappears without a proven
// alias migration, require a fresh explicit choice instead of guessing a tab.
if (last) {
return null;
}
// Prefer a real page tab first (avoid service workers/background targets).
const page = candidates.find((t) => (t.type ?? "page") === "page");
return page ?? candidates.at(0) ?? null;
};
const chosen = targetId ? resolveById(targetId) : pickDefault();
if (chosen === "AMBIGUOUS") {
throw new BrowserTargetAmbiguousError();
}
if (!chosen) {
throw new BrowserTabNotFoundError({ input: targetId ?? stickyTargetId });
}
runtime.lastTargetId = chosen.targetId;
return chosen;
};
const resolveTargetIdOrThrow = async (
targetId: string,
options?: BrowserTabTargetOptions,
): Promise<string> => {
const tabs = await listTabs(options);
if (options?.exactTargetId) {
const exactTarget = tabs.find((tab) => tab.targetId === targetId);
if (!exactTarget) {
throw new BrowserTabNotFoundError({ input: targetId });
}View on GitHub (pinned to 01804a7531)
Solutions
- Use action=tabs to list current tabs and pass a more specific suggestedTargetId, tabId, label, or raw targetId.
- Pass exactTargetId:true to bypass alias resolution and match the raw targetId directly.
- Close duplicate tabs so the alias is unique.
- Use a raw targetId (longest, most specific identifier) instead of a short label.
Example fix
// before: ambiguous label
await browser.tab('chat'); // matches 3 tabs
// after: disambiguate with raw targetId from action=tabs
await browser.tab('A1B2C3D4...targetId', { exactTargetId: true }); Defensive patterns
Strategy: validation
Validate before calling
// Resolve the tab id against current tabs before acting; detect ambiguity upfront
async function resolveUniquely(targetId: string, tabs): Promise<string | null> {
const matches = tabs.filter(t => t.label === targetId || t.alias === targetId);
if (matches.length > 1) return null; // ambiguous
return matches[0]?.targetId ?? null;
} Type guard
import { BrowserTargetAmbiguousError } from './errors';
function isTabAmbiguous(err: unknown): err is BrowserTargetAmbiguousError {
return err instanceof BrowserTargetAmbiguousError;
} Try / catch
try {
await browser.tab(targetId);
} catch (err) {
if (err instanceof BrowserTargetAmbiguousError) {
const tabs = await browser.tabs();
// ask the user / caller to disambiguate using a raw targetId
throw new Error(`ambiguous; candidates: ${tabs.map(t => t.targetId).join(', ')}`, { cause: err });
}
throw err;
} Prevention
- Always use a raw targetId (exactTargetId:true) when you have one.
- Call action=tabs first and pick a unique identifier.
- Close duplicate tabs so aliases don't collide.
- Avoid short shorthands that match multiple titles.
When it happens
Trigger: listTabs() called with a targetId that resolves via resolveTargetIdFromTabs which returns { ok:false, reason:'ambiguous' }, and no exactTargetId override was supplied.
Common situations: Two tabs share the same label/alias; a shorthand matches multiple tab titles; positional/tabId alias collides after tabs were duplicated; the user opened two identical pages.
Related errors
- tab not found: browser tab "${input}" not found. Use action=
- tab ${tabId} is not available to OpenClaw
- tab ${tabId} closed during attach
- Multiple dialogs are pending; pass dialogId.
- ambiguous browser tab reference
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/410dd5bf9af3929f.
Report an issue: GitHub.