microsoft/playwright · error · ValidationError

${path}: expected channel ${names.toString()}

Error message

${path}: expected channel ${names.toString()}

What it means

Thrown by _tChannelImplFromWire when the referenced object exists in _objects but its _type is not in the allowed names list (and names !== '*'). The server sent an object handle where a specific channel type was expected, but the handle's actual type differs — a protocol contract violation on the wire.

Source

Thrown at packages/playwright-core/src/client/connection.ts:307

  }

  close(cause?: string) {
    if (this._closedError)
      return;
    this._closedError = new TargetClosedError(cause);
    for (const callback of this._callbacks.values())
      callback.reject(this._closedError);
    this._callbacks.clear();
    this.emit('close');
  }

  private _tChannelImplFromWire(names: '*' | string[], arg: any, path: string, context: ValidatorContext) {
    if (arg && typeof arg === 'object' && typeof arg.guid === 'string') {
      const object = this._objects.get(arg.guid)!;
      if (!object)
        throw new Error(`Object with guid ${arg.guid} was not bound in the connection`);
      if (names !== '*' && !names.includes(object._type))
        throw new ValidationError(`${path}: expected channel ${names.toString()}`);
      return object._channel;
    }
    throw new ValidationError(`${path}: expected channel ${names.toString()}`);
  }

  private _createRemoteObject(parentGuid: string, type: string, guid: string, initializer: any): any {
    const parent = this._objects.get(parentGuid);
    if (!parent)
      throw new Error(`Cannot find parent object ${parentGuid} to create ${guid}`);
    const validator = findValidator(type, '', 'Initializer');
    initializer = validator(initializer, '', this._validatorFromWireContext());
    const factory = this._objectFactories.get(type);
    if (!factory)
      throw new Error('Missing type ' + type);
    return factory(parent, type, guid, initializer);
  }
}

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Match client and server Playwright versions.
  2. If running a patched server, verify it returns the correct object type for each channel-typed field per protocol.yml.
  3. Reproduce with DEBUG=pw:channel and confirm the offending field and the actual type received.
Defensive patterns

Strategy: validation

Try / catch

try {
  await page.someApiCallReturningObject();
} catch (e) {
  if (/expected channel/.test(String(e?.message))) {
    // Server returned the wrong object type — almost always a version mismatch.
    throw new Error('Client/server Playwright version mismatch: ' + e.message);
  }
  throw e;
}

Prevention

When it happens

Trigger: A method/event parameter validated as e.g. 'Page' or 'Frame' carries a guid whose object is a different type (Browser, Request, etc.). Indicates a server bug, version skew, or a custom server emitting the wrong object kind for a field.

Common situations: Client/server version mismatch where a field's expected type changed; unofficial server returning mismatched object kinds; a malformed response from a patched server.

Related errors


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