openclaw/openclaw · warning · BrowserTargetAmbiguousError
ambiguous browser tab reference
Error message
ambiguous browser tab reference
What it means
BrowserTargetAmbiguousError (HTTP 409) thrown inside labelTab when resolveTargetIdFromTabs returns {ok:false, reason:'ambiguous'}. The supplied targetId/label/prefix matched more than one live tab across the exact-match namespace (targetId, suggestedTargetId, tabId, label) or the raw target-id prefix namespace. The runtime fails closed rather than guessing which tab to relabel.
Solutions
- Pass the full raw targetId (or a longer unique prefix) returned from action=tabs.
- Use suggestedTargetId or tabId from the tabs list for an exact, unique reference.
- Rename/deduplicate labels so only one tab carries the alias you intend to target.
- Call listTabs first, inspect matches, and pass a value that resolves uniquely.
Example fix
// before
await labelTab("docs", "primary"); // multiple tabs labeled/starting 'docs'
// after
const tabs = await listTabs();
const exact = tabs.find(t => t.tabId === "t7");
await labelTab(exact.targetId, "primary"); Defensive patterns
Strategy: validation
Validate before calling
import { resolveTargetIdFromTabs } from "./target-id.js";
const tabs = await listTabs();
const r = resolveTargetIdFromTabs(input, tabs);
if (!r.ok) {
if (r.reason === "ambiguous") {
// pick a longer/unique prefix or an exact tabId, then retry
}
} Try / catch
try { await labelTab(input, label); }
catch (err) {
if (err.status === 409 && /ambiguous/.test(err.message)) {
// re-list, disambiguate by passing full targetId or tabId
} else throw err;
} Prevention
- Always pass the full targetId (or a unique tabId) returned from listTabs.
- Keep labels unique to avoid exact-match ambiguity.
- Resolve references via resolveTargetIdFromTabs before mutating.
When it happens
Trigger: labelTab(targetId, label) is called with an input whose exact-match set resolves to >1 distinct targetId, or whose lowercased prefix matches >1 targetId. Examples: two tabs share a label alias; a short prefix like 'AB' matches multiple targetIds; a tabId collides with a raw targetId.
Common situations: User passes a short/ambiguous prefix; a label was reused across tabs; stale aliases survived a tab restart. The cross-namespace collision guard also fires when a friendly id and a raw id both happen to match.
Related errors
- tab not found: browser tab
- ambiguous browser tab reference
- Multiple dialogs are pending; pass dialogId.
- tab label must be 1-64 chars and use only letters, numbers…
- act:evaluate is disabled by config…
AI-assisted analysis of openclaw/openclaw@01804a7531 (2026-08-12).
Data as JSON: /api/errors/df69c3241c379fbe.
Report an issue: GitHub.
Appendix: source
Thrown at extensions/browser/src/browser/server-context.tab-ops.ts:486
type: created.type,
},
opts,
),
{ ...opts, label: normalizedLabel },
);
};
const labelTab = async (
targetId: string,
label: string,
options?: BrowserOperationOptions,
): Promise<BrowserTab> => {
const normalizedLabel = normalizeTabLabel(label);
const tabs = await listTabs(options);
const resolved = resolveTargetIdFromTabs(targetId, tabs);
if (!resolved.ok) {
if (resolved.reason === "ambiguous") {
throw new BrowserTargetAmbiguousError();
}
throw new BrowserTabNotFoundError({ input: targetId });
}
const tab = tabs.find((candidate) => candidate.targetId === resolved.targetId);
if (!tab) {
throw new BrowserTabNotFoundError({ input: targetId });
}
return assignTabAlias({ profileState: runtime, tab, label: normalizedLabel });
};
return {
listTabs,
openTab,
labelTab,
};
}
View on GitHub (pinned to 01804a7531)