CherryHQ/cherry-studio · error · Error
Tab ${tabId} not found
Error message
Tab ${tabId} not found What it means
After resolving a window for the mode, switchTab looks up windowInfo.tabs.get(tabId); if absent it throws 'Tab ${tabId} not found'. The tab may have been closed (webContents 'destroyed' deletes the entry) or the tabId was never created in that window.
Source
Thrown at src/main/ai/mcp/servers/browser/controller.ts:931
* @param privateMode - If true, closes tab from private window (default: false)
* @param tabId - Tab identifier to close
*/
public async closeTab(privateMode: boolean, tabId: string) {
await this.reset(privateMode, tabId)
}
/**
* Switches the active tab
* @param privateMode - If true, switches tab in private window (default: false)
* @param tabId - Tab identifier to switch to
*/
public async switchTab(privateMode: boolean, tabId: string) {
const windowKey = this.getWindowKey(privateMode)
const windowInfo = this.windows.get(windowKey)
if (!windowInfo) throw new Error(`Window not found for ${privateMode ? 'private' : 'normal'} mode`)
const tab = windowInfo.tabs.get(tabId)
if (!tab) throw new Error(`Tab ${tabId} not found`)
// Remove previous active tab view (but NOT the tabBarView)
if (windowInfo.activeTabId && windowInfo.activeTabId !== tabId) {
const prevTab = windowInfo.tabs.get(windowInfo.activeTabId)
if (prevTab && !windowInfo.window.isDestroyed()) {
windowInfo.window.removeBrowserView(prevTab.view)
}
}
windowInfo.activeTabId = tabId
// Add the new active tab view
if (!windowInfo.window.isDestroyed()) {
windowInfo.window.addBrowserView(tab.view)
this.updateViewBounds(windowInfo)
}
this.touchTab(windowKey, tabId)View on GitHub (pinned to 726446b54c)
Solutions
- Validate the tabId against the window's current tabs before calling switchTab; re-enumerate if stale.
- Ensure the privateMode flag matches the mode the tabId was created under.
- Handle 'tab not found' by falling back to the active tab or creating a fresh one.
- Avoid caching tabIds long-term; re-query the controller's list_tabs.
Example fix
// before
const tab = windowInfo.tabs.get(tabId)
if (!tab) throw new Error(`Tab ${tabId} not found`)
// after — fall back to active tab or create one
let tab = windowInfo.tabs.get(tabId)
if (!tab) {
if (windowInfo.activeTabId) {
tab = windowInfo.tabs.get(windowInfo.activeTabId)
}
if (!tab) {
const created = await this.createTab(privateMode, false)
tab = windowInfo.tabs.get(created.tabId)
}
if (!tab) throw new Error(`Tab ${tabId} not found and no fallback available`)
} Defensive patterns
Strategy: validation
Validate before calling
// Verify the tabId is live in the target window before switching
function tabExists(controller, privateMode, tabId) {
const windowKey = controller.getWindowKey(privateMode)
const windowInfo = controller.windows.get(windowKey)
return !!windowInfo && windowInfo.tabs.has(tabId) && !windowInfo.tabs.get(tabId).view.webContents.isDestroyed()
} Type guard
function isLiveTab(windowInfo, tabId): boolean {
const t = windowInfo?.tabs?.get(tabId)
return !!t && !t.view.webContents.isDestroyed()
} Try / catch
if (!tabExists(controller, privateMode, tabId)) {
return { content: [{ type: 'text', text: `Tab ${tabId} no longer exists` }], isError: true }
} Prevention
- Do not cache tabIds long-term; re-enumerate via list_tabs.
- Match privateMode to the tab's originating window.
- Fall back to the active tab when the requested one is gone.
When it happens
Trigger: Agent passes a tabId from a different window/mode; the tab was already closed via closeTab/closeTabInternal; the webContents 'destroyed' event removed it; or a stale tabId cached by the agent.
Common situations: Agent holds an old tabId across a reset/close; mode mismatch (normal-mode tabId used in private mode); tab crashed and auto-removed; concurrent closeTab raced switchTab.
Related errors
- Tab ${freshTabId} was created but not found - it may have be
- Tab ${newTabId} was created but not found - it may have been
- Window not found for ${privateMode ? 'private' : 'normal'} m
- MCP browser window not found after open
- Tool not found
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/51811b4536c7c576.
Report an issue: GitHub.