microsoft/playwright · error · Error

Unknown method: ${method}

Error message

Unknown method: ${method}

What it means

Thrown by the CLI daemon's socket message handler when the inbound `method` is neither `'stop'` nor `'run'`. The daemon protocol recognizes exactly two methods; any other value falls into the `else` branch and is rejected. The error is caught and sent back over the socket as the response error, not rethrown.

Source

Thrown at packages/playwright-core/src/tools/cli-daemon/daemon.ts:99

    const abortController = new AbortController();
    connection.onclose = () => abortController.abort();
    connection.onmessage = async message => {
      const { id, method, params } = message;
      try {
        if (method === 'stop') {
          await deleteSessionFile(clientInfo, sessionConfig);
          const sendAck = async () => connection.send({ id, result: 'ok' }).catch(() => {});
          if (options?.exitOnClose)
            gracefullyProcessExitDoNotHang(0, () => sendAck());
          else
            await sendAck();
        } else if (method === 'run') {
          const { toolName, toolParams } = parseCliCommand(params.args);
          toolParams._meta = { cwd: params.cwd, raw: params.raw || params.json, json: !!params.json };
          const response = await backend.callTool(toolName, toolParams, abortController.signal);
          await connection.send({ id, result: formatResult(response) });
        } else {
          throw new Error(`Unknown method: ${method}`);
        }
      } catch (e) {
        const error = process.env.PWDEBUGIMPL ? (e as Error).stack || (e as Error).message : (e as Error).message;
        connection.send({ id, error }).catch(() => {});
      }
    };
  });

  decorateServer(server);
  browserContext.on('close', () => Promise.resolve().then(async () => {
    await deleteSessionFile(clientInfo, sessionConfig);
    if (options?.exitOnClose)
      gracefullyProcessExitDoNotHang(0);
  }));

  await new Promise<void>((resolve, reject) => {
    server.on('error', reject);
    server.listen(socketPath, () => resolve());

View on GitHub (pinned to c8fc3bf8d3)

Solutions

  1. Send only `method: "run"` (with `params.args`/`params.cwd`) or `method: "stop"`.
  2. Verify the CLI client and daemon are the same Playwright version (a newer method is not supported by an older daemon).
  3. Inspect the exact `method` string in the error to spot typos or undefined values caused by a malformed payload.

Example fix

// before
connection.send({ id: 1, method: 'list', params: {} });
// after
connection.send({ id: 1, method: 'run', params: { args: { _: ['screenshot'], target: 'ref' }, cwd: process.cwd() } });
Defensive patterns

Strategy: validation

Validate before calling

const KNOWN_METHODS = new Set(['run', 'stop']);
function buildFrame(id: number, method: string, params: any) {
  if (!KNOWN_METHODS.has(method))
    throw new TypeError(`Unsupported daemon method: ${method}`);
  return { id, method, params };
}

Type guard

type DaemonMethod = 'run' | 'stop';
function isDaemonMethod(m: string): m is DaemonMethod {
  return m === 'run' || m === 'stop';
}

Prevention

When it happens

Trigger: A client (CLI client, test harness, or custom script) sends a JSON message whose `method` field is anything other than `"stop"` or `"run"` (e.g. `"ping"`, `"list"`, a typo like `"runn"`, or an undefined field due to a malformed payload).

Common situations: Version skew between the CLI client and daemon (client uses a method added in a newer version); a hand-rolled socket client sending the wrong frame shape; a test that sends raw JSON without going through the SocketConnection helper.

Related errors


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