microsoft/playwright · error · Error

Passing a ConnectionTransport to connectOverCDP is not suppo

Error message

Passing a ConnectionTransport to connectOverCDP is not supported when connecting remotely.

What it means

Thrown in connectOverCDP() when a ConnectionTransport is passed AND the connection itself is remote (this._connection.isRemote()). Passing a raw transport (send/close) only works when the client owns the local process; a thin client forwarding to another server cannot relay an arbitrary transport object.

Source

Thrown at packages/playwright-core/src/client/browserType.ts:153

      return browser;
    });
  }

  async connectOverCDP(options: api.ConnectOverCDPOptions  & { wsEndpoint?: string }): Promise<api.Browser>;
  async connectOverCDP(endpointURL: string, options?: api.ConnectOverCDPOptions): Promise<api.Browser>;
  async connectOverCDP(transport: api.ConnectOverCDPTransport, options?: api.ConnectOverCDPOptions): Promise<api.Browser>;
  async connectOverCDP(overloaded: (api.ConnectOverCDPOptions & { wsEndpoint?: string }) | string | api.ConnectOverCDPTransport, options?: api.ConnectOverCDPOptions): Promise<Browser> {
    let endpointURL: string | undefined;
    let transport: api.ConnectOverCDPTransport | undefined;
    let params: api.ConnectOverCDPOptions;
    if (typeof overloaded === 'string') {
      endpointURL = overloaded;
      params = options ?? {};
    } else if (isConnectionTransport(overloaded)) {
      if (this.name() !== 'chromium' && this.name() !== 'webkit')
        throw new Error('Connecting over CDP is only supported in Chromium and WebKit.');
      if (this._connection.isRemote())
        throw new Error('Passing a ConnectionTransport to connectOverCDP is not supported when connecting remotely.');
      transport = overloaded;
      params = options ?? {};
    } else {
      endpointURL = 'endpointURL' in overloaded ? (overloaded as any).endpointURL : overloaded.wsEndpoint;
      assert(endpointURL, 'Cannot connect over CDP without wsEndpoint.');
      params = overloaded;
    }
    if (endpointURL && this.name() !== 'chromium' && this.name() !== 'webkit')
      throw new Error('Connecting over CDP is only supported in Chromium and WebKit.');

    const result = await this._channel.connectOverCDP({
      endpointURL,
      transport: transport as any,
      headers: params.headers ? headersObjectToArray(params.headers) : undefined,
      slowMo: params.slowMo,
      isLocal: params.isLocal,
      noDefaults: params.noDefaults,
      artifactsDir: params.artifactsDir,

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Use the endpointURL overload from thin clients: `connectOverCDP('ws://...')`.
  2. Run from the full playwright-core package where the connection is local.
  3. Implement the CDP bridge on the server side and expose a WS endpoint instead.

Example fix

// before
await chromium.connectOverCDP({ send, close }); // from thin client
// after
await chromium.connectOverCDP('ws://localhost:9222/devtools/browser/...');
Defensive patterns

Strategy: type-guard

Validate before calling

const isRemote = (browserType as any)._connection?.isRemote?.();
if (isRemote && isTransportArg(arg))
  throw new Error('Cannot pass a transport from a thin client; pass an endpoint URL.');

Type guard

function isConnectionTransport(v: any): boolean {
  return !!v && typeof v === 'object'
    && typeof v.send === 'function' && typeof v.close === 'function';
}

Prevention

When it happens

Trigger: Using playwright-client/thin mode and calling `chromium.connectOverCDP({ send, close })`. isConnectionTransport is true, name is chromium, but isRemote() is true.

Common situations: Reusing a transport-based CDP snippet from a full-client setup inside a remote/thin deployment; bridging two hops (client -> server -> CDP) which the transport API doesn't support.

Related errors


AI-assisted analysis of microsoft/playwright@c8fc3bf8d3 (2026-08-12). Data as JSON: /api/errors/868f1300bd9d7a95. Report an issue: GitHub.