n8n-io/n8n · warning · AlreadyConnectedError
Already connected to a browser
Error message
Already connected to a browser
What it means
AlreadyConnectedError is thrown by BrowserConnection.connect when this.state is already set — a prior connect() succeeded and the connection is live. The connection enforces single-active-session semantics; calling connect twice without an intervening disconnect is a programming error.
Source
Thrown at packages/@n8n/mcp-browser/src/connection.ts:95
});
}
}
this.config = {
defaultBrowser: parsed.defaultBrowser,
browsers,
adapter: parsed.adapter,
mode: parsed.mode,
};
}
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
async connect(overrideBrowser?: BrowserName): Promise<ConnectResult> {
if (this.state) {
throw new AlreadyConnectedError();
}
const browser = overrideBrowser ?? this.config.defaultBrowser;
if (this.config.mode !== 'remote') {
this.requireBrowserAvailable(browser);
}
const connectConfig: ConnectConfig = {
browser,
};
// Reuse a pending adapter (relay kept alive from a prior timeout) if available.
const adapter = this.pendingAdapter ?? (await this.createAdapter());
this.pendingAdapter = null;
// Listen for unexpected disconnections so we can invalidate state immediately
adapter.onDisconnect = (reason) => {
if (!this.state) return; // already disconnectedView on GitHub (pinned to 5ac6606e81)
Solutions
- Check connection.isConnected before calling connect, or call disconnect first.
- Make connect idempotent in your wrapper: if (connection.isConnected) return;
- In retry loops, ensure disconnect() runs before any reconnect attempt.
Example fix
// before — double connect
await connection.connect();
await connection.connect(); // throws AlreadyConnectedError
// after — guard with isConnected
if (!connection.isConnected) { await connection.connect(); } Defensive patterns
Strategy: validation
Validate before calling
if (connection.isConnected) { /* already connected, skip */ return; }
await connection.connect(); Type guard
function isConnected(c: BrowserConnection): boolean {
return c.isConnected;
} Try / catch
try {
await connection.connect();
} catch (e) {
if (e instanceof AlreadyConnectedError) { /* no-op, already live */ }
else throw e;
} Prevention
- Guard every connect call with isConnected.
- Make your agent's connect wrapper idempotent.
- Always pair connect/disconnect; never assume a clean slate.
When it happens
Trigger: Invoking browser_connect when a connection already exists (isConnected === true). Common in agent loops that reconnect defensively without first checking state, or in retry logic that re-enters connect after a partial success.
Common situations: Agent retries connect after a slow-but-successful first attempt. Two concurrent tool calls both triggering a lazy connect. User-script calls connect in a loop without disconnect.
Related errors
- Not connected to a browser
- Cannot decrease maxIterations when resuming a run. Expected
- Checkpoint for runId ${this.runId} has pending tool calls —
- Model ID is required
- Invalid model ID "${rawId}": expected "provider/model-name"
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/2cb93a2aa6abf883.
Report an issue: GitHub.