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

  1. Pass the full raw targetId (or a longer unique prefix) returned from action=tabs.
  2. Use suggestedTargetId or tabId from the tabs list for an exact, unique reference.
  3. Rename/deduplicate labels so only one tab carries the alias you intend to target.
  4. 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

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


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)