jackwener/OpenCLI · error · Error

Failed to create tab in automation container

Error message

Failed to create tab in automation container

What it means

As a last resort resolveTab creates a blank tab in the automation container window; if chrome.tabs.create returns a tab without an id (creation failed), the library throws a generic Error because it cannot group or track a tab without an id. This indicates the Chrome tabs API failed to create the tab.

Source

Thrown at extension/src/background.ts:1590

  // without a group signal must create a fresh tab rather than overwrite user
  // content in a window where an OpenCLI group may have disappeared.
  const tabs = await chrome.tabs.query({ windowId: scopedWindowId });
  const reuseTab = existingSession?.owned ? undefined : tabs.find(t => t.id);
  if (reuseTab?.id) {
    await chrome.tabs.update(reuseTab.id, { url: BLANK_PAGE });
    await new Promise(resolve => setTimeout(resolve, 300));
    try {
      const updated = await chrome.tabs.get(reuseTab.id);
      if (isDebuggableUrl(updated.url)) return { tabId: reuseTab.id, tab: updated };
      console.warn(`[opencli] data: URI was intercepted (${updated.url}), creating fresh tab`);
    } catch {
      // Tab was closed during navigation
    }
  }

  // Fallback: create a new tab
  const newTab = await chrome.tabs.create({ windowId: scopedWindowId, url: BLANK_PAGE, active: true });
  if (!newTab.id) throw new Error('Failed to create tab in automation container');
  await ensureOwnedContainerGroup(role, scopedWindowId, [newTab.id]);
  return { tabId: newTab.id, tab: await chrome.tabs.get(newTab.id) };
}

/** Build a page-scoped success result with targetId resolved from tabId */
async function pageScopedResult(id: string, tabId: number, data?: unknown): Promise<Result> {
  const page = await identity.resolveTargetId(tabId);
  return { id, ok: true, data, page };
}

/** Convenience wrapper returning just the tabId (used by most handlers) */
async function resolveTabId(tabId: number | undefined, leaseKey: string, initialUrl?: string): Promise<number> {
  const resolved = await resolveTab(tabId, leaseKey, initialUrl);
  return resolved.tabId;
}

async function listAutomationTabs(leaseKey: string): Promise<chrome.tabs.Tab[]> {
  const session = automationSessions.get(leaseKey);

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command; transient window teardown often resolves on a second attempt
  2. Verify the automation container window still exists (opencli browser open to recreate it)
  3. Re-create the automation container/window before running tab commands
  4. Check Chrome extension error console for tabs API permission or lifecycle errors

Example fix

// before
const newTab = await chrome.tabs.create({ windowId: staleWindowId, ... });
if (!newTab.id) throw new Error('Failed to create tab in automation container');
// after
const win = await chrome.windows.get(scopedWindowId);   // validate window first
const newTab = await chrome.tabs.create({ windowId: win.id, ... });
Defensive patterns

Strategy: retry

Validate before calling

try { await chrome.windows.get(scopedWindowId); } catch {
  throw new Error('automation window gone; recreate container first');
}

Type guard

async function windowIsValid(windowId: number): Promise<boolean> {
  try { await chrome.windows.get(windowId); return true; } catch { return false; }
}

Try / catch

try {
  await cmd();
} catch (e) {
  if ((e as Error).message.includes('Failed to create tab')) {
    await recreateContainerWindow();
    return retry(cmd, { attempts: 2 });
  }
  throw e;
}

Prevention

When it happens

Trigger: chrome.tabs.create({ windowId: scopedWindowId, url: BLANK_PAGE, active: true }) returns a Tab whose id is undefined/null — no valid tabId exists for ensureOwnedContainerGroup.

Common situations: Invalid or closed scopedWindowId, Chrome window destroyed mid-creation, extension lacking 'tabs' permission context changes, Chrome profile shutting down during automation.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/4f21b363f7cbe840. Report an issue: GitHub.