stablyai/orca · warning · BrowserError

browser_target_ambiguous

browser_target_ambiguous

Error message

Multiple worktrees have browser tabs open; pass --worktree to target text insertion safely

What it means

Thrown by resolveScopedActiveTab when more than one worktree has at least one live browser tab and no worktreeId was provided. Because text-mutation commands could inject into the wrong worktree's foreground webview and steal focus, the resolver refuses to guess — it demands an explicit --worktree flag. This is a safety guard, not a crash.

Source

Thrown at src/main/browser/agent-browser-bridge.ts:2279

  // Why: don't fall back to the global tab for text mutation — it could inject into another worktree's foreground webview and steal focus.
  private resolveScopedActiveTab(worktreeId?: string): ResolvedBrowserCommandTarget {
    if (worktreeId) {
      return this.resolveActiveTab(worktreeId)
    }

    const worktreesWithLiveTabs = new Set<string | undefined>()
    for (const [tabId, wcId] of this.getRegisteredTabs(undefined)) {
      if (this.getWebContents(wcId)) {
        worktreesWithLiveTabs.add(this.browserManager.getWorktreeIdForTab(tabId))
      }
    }

    if (worktreesWithLiveTabs.size === 0) {
      throw new BrowserError('browser_no_tab', 'No browser tab open in this worktree')
    }
    if (worktreesWithLiveTabs.size > 1) {
      throw new BrowserError(
        'browser_target_ambiguous',
        'Multiple worktrees have browser tabs open; pass --worktree to target text insertion safely'
      )
    }

    const [onlyWorktreeId] = worktreesWithLiveTabs
    return this.resolveActiveTab(onlyWorktreeId)
  }

  private async ensureSession(
    sessionName: string,
    browserPageId: string,
    webContentsId: number
  ): Promise<void> {
    const pendingDestruction = this.pendingSessionDestruction.get(sessionName)
    if (pendingDestruction) {
      await pendingDestruction
    }

View on GitHub (pinned to 1136503c6a)

Solutions

  1. Pass the correct worktreeId when calling the text-mutation command — the message explicitly recommends `--worktree`.
  2. If operating in a single-worktree context, ensure other worktrees' tabs are closed so the resolver can auto-target the sole remaining one.
  3. Track the active worktree in the agent's command context and propagate it to all browser text commands.
Defensive patterns

Strategy: validation

Validate before calling

// before calling a text-mutation command, check if disambiguation is needed
const worktrees = bridge.getWorktreesWithLiveTabs()
if (worktrees.size > 1 && !worktreeId) {
  // must pass worktreeId to avoid ambiguity
}

Try / catch

try {
  return await bridge.type(text) // no worktreeId
} catch (e) {
  if (e instanceof BrowserError && e.code === 'browser_target_ambiguous') {
    // caller must supply the correct worktreeId
    throw new Error('Ambiguous target: specify worktreeId')
  }
  throw e
}

Prevention

When it happens

Trigger: A text-insertion command (type, fill, select-all, focus-element) is called without worktreeId while two or more worktrees each have live browser tabs. resolveScopedActiveTab collects worktreesWithLiveTabs, finds size > 1, and throws browser_target_ambiguous. The message tells the caller to pass --worktree.

Common situations: User/agent has multiple worktree sessions open, each with a browser tab, and issues a type command without specifying which worktree; agent loop didn't track which worktree it's operating in; multi-worktree development session with concurrent browser panels.

Related errors


AI-assisted analysis of stablyai/orca@1136503c6a (2026-08-12). Data as JSON: /api/errors/8f292e12b3c62839. Report an issue: GitHub.