n8n-io/n8n · critical · ConnectionLostError
Browser connection lost: The browser extension disconnected
Error message
Browser connection lost: The browser extension disconnected
What it means
ConnectionLostError('extension_disconnected') is thrown in the Target.attachToTarget CDP handler when this.extensionConn is null. The relay translates Playwright's CDP Target.attachToTarget into an extension 'attachTab' message; if the extension WebSocket is gone, the translation cannot proceed. This indicates the extension side of the bridge dropped.
Source
Thrown at packages/@n8n/mcp-browser/src/cdp-relay.ts:433
const tabs = await this.listTabs();
return {
targetInfos: tabs.map((entry) => ({
targetId: entry.id,
type: 'page',
title: entry.title,
url: entry.url,
attached: false,
browserContextId: this.browserContextId,
})),
};
}
case 'Target.setDiscoverTargets':
return {};
case 'Target.attachToTarget': {
const targetId = (params as { targetId: string })?.targetId;
if (!this.extensionConn) throw new ConnectionLostError('extension_disconnected');
await this.extensionConn.send('attachTab', { id: targetId });
return { sessionId: targetId };
}
case 'Target.setAutoAttach': {
// Child session auto-attach: forward to extension so Chrome attaches to iframes
if (sessionId) {
return await this.forwardToExtension(method, params, sessionId);
}
// Root-level: forward to extension (applies to all attached tabs) AND list tabs for cache
log.debug('Target.setAutoAttach: forwarding to extension and listing tabs');
await this.forwardToExtension(method, params, sessionId);
const { tabs } = (await this.extensionConn!.send('listRegisteredTabs', {})) as {
tabs: Array<{ id: string; title: string; url: string }>;
};
log.debug('listRegisteredTabs result:', tabs.length, 'tabs');View on GitHub (pinned to 5ac6606e81)
Solutions
- Call browser_disconnect then browser_connect to re-establish the extension bridge.
- Ensure the n8n AI Browser Bridge extension is installed, enabled, and not suspended (Chrome service-worker eviction).
- Keep the session active with periodic interaction to prevent service-worker suspension.
Example fix
// before — operating after extension dropped await connection.getConnection(); // ConnectionLostError propagates // after — reconnect await connection.disconnect(); await connection.connect();
Defensive patterns
Strategy: retry
Validate before calling
if (!relay.extensionConn) { await connection.disconnect(); await connection.connect(); } Type guard
function extensionAlive(relay: CdpRelay): boolean {
return relay.extensionConn !== null;
} Try / catch
try {
await relay.handleCdp('Target.attachToTarget', params);
} catch (e) {
if (e instanceof ConnectionLostError) {
await connection.disconnect();
await connection.connect();
await relay.handleCdp('Target.attachToTarget', params);
} else throw e;
} Prevention
- Monitor the extension WebSocket close event and proactively reconnect.
- Keep the extension service worker alive with periodic activity.
- Surface disconnect to the user immediately rather than letting commands fail.
When it happens
Trigger: Playwright issues Target.attachToTarget (during page auto-attach or explicit attach) after the extension connection was closed — e.g. the extension was uninstalled, the browser was quit, or the WebSocket closed and extensionConn was nulled on close.
Common situations: User closed the browser while a session was active. Extension crashed or was reloaded. Network interruption dropped the WebSocket and handleClose() nulled extensionConn. Long-idle session where the extension's service worker was evicted.
Related errors
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/7f1749c7aa21947a.
Report an issue: GitHub.