CherryHQ/cherry-studio · error · Error
Tab ${newTabId} was created but not found - it may have been
Error message
Tab ${newTabId} was created but not found - it may have been closed What it means
Same creation race as error 249 but in the fallback branch of getActiveOrCreateTab: when there is no usable active tab and no supplied tabId, the code calls createTab then immediately looks up the new tabId in windowInfo.tabs. If webContents 'destroyed' has already deleted it, the lookup fails.
Source
Thrown at src/main/ai/mcp/servers/browser/controller.ts:596
this.touchTab(windowInfo.windowKey, tabId)
return { tabId, tab }
}
}
// Use active tab or create new one
if (windowInfo.activeTabId) {
const activeTab = windowInfo.tabs.get(windowInfo.activeTabId)
if (activeTab && !activeTab.view.webContents.isDestroyed()) {
this.touchTab(windowInfo.windowKey, windowInfo.activeTabId)
return { tabId: windowInfo.activeTabId, tab: activeTab }
}
}
// Create new tab
const { tabId: newTabId } = await this.createTab(privateMode, showWindow)
const tab = windowInfo.tabs.get(newTabId)
if (!tab) {
throw new Error(`Tab ${newTabId} was created but not found - it may have been closed`)
}
return { tabId: newTabId, tab }
}
/**
* Opens a URL in a browser window and waits for navigation to complete.
* @param url - The URL to navigate to
* @param timeout - Navigation timeout in milliseconds (default: 10000)
* @param privateMode - If true, uses private browsing mode (default: false)
* @param newTab - If true, always creates a new tab (useful for parallel requests)
* @param showWindow - If true, shows the browser window (default: false)
* @returns Object containing the current URL, page title, and tab ID after navigation
*/
public async open(url: string, timeout = 10000, privateMode = false, newTab = false, showWindow = false) {
// Reject non-http(s) schemes (e.g. file://) and local/private hosts before navigating
// (covers fetch() too, which routes through open()) to prevent local-file read / SSRF.
url = sanitizeRemoteUrl(url)
View on GitHub (pinned to 726446b54c)
Solutions
- Retry createTab once, and if it still fails, surface a deterministic 'unable to create browser tab' error.
- Add an isDisposing guard so requests during teardown short-circuit instead of racing destruction.
- Check Electron logs for render-process/GPU crashes on BrowserView construction.
- Ensure getOrCreateWindow has fully settled (await ensureAppReady) before creating tabs.
Example fix
// before
const { tabId: newTabId } = await this.createTab(privateMode, showWindow)
const tab = windowInfo.tabs.get(newTabId)
if (!tab) {
throw new Error(`Tab ${newTabId} was created but not found - it may have been closed`)
}
// after — single retry + teardown guard
let created = await this.createTab(privateMode, showWindow)
let tab = windowInfo.tabs.get(created.tabId)
if (!tab && !this.disposing) {
created = await this.createTab(privateMode, showWindow)
tab = windowInfo.tabs.get(created.tabId)
}
if (!tab) throw new Error('Unable to create browser tab (webContents destroyed)')
return { tabId: created.tabId, tab } Defensive patterns
Strategy: try-catch
Validate before calling
async function ensureActiveTab(controller, windowInfo, privateMode, showWindow) {
let created = await controller.createTab(privateMode, showWindow)
let tab = windowInfo.tabs.get(created.tabId)
if (!tab && !controller.disposing) {
created = await controller.createTab(privateMode, showWindow)
tab = windowInfo.tabs.get(created.tabId)
}
if (!tab) throw new Error('unable to create a usable browser tab')
return { tabId: created.tabId, tab }
} Try / catch
try {
return await ensureActiveTab(controller, windowInfo, privateMode, showWindow)
} catch (e) {
if (controller.disposing) throw new Error('browser controller shutting down')
throw e
} Prevention
- Ensure ensureAppReady has settled before creating tabs.
- Stop issuing browser calls once disposal begins.
- Monitor for render-process crashes that destroy new views instantly.
When it happens
Trigger: The first/only tab in a window is created and its webContents is destroyed before the creating call returns — e.g. app shutting down, GPU process crash, sandbox init failure, or a concurrent dispose.
Common situations: First navigation request hitting browser tool during shutdown; Electron failing to spawn the render process for the new tab; concurrent closeTab/dispose racing the implicit 'create first tab' path.
Related errors
- Tab ${freshTabId} was created but not found - it may have be
- MCP browser window not found after open
- Window not found for ${privateMode ? 'private' : 'normal'} m
- Tab ${tabId} not found
- Unknown script error
AI-assisted analysis of CherryHQ/cherry-studio@726446b54c (2026-08-12).
Data as JSON: /api/errors/34b7e7861480d66b.
Report an issue: GitHub.