Skip to content

Client.destroy may hang after Browser disconnected, preventing cleanup (pupBrowser.close() never resolves/rejects) #3846

@Adi1231234

Description

@Adi1231234

Is there an existing issue for this?

  • I have searched the existing issues.

Is this a problem caused by your code, or is it specifically because of the library?

  • I have double-checked my code carefully.

Describe the bug.

Sometimes the communication to pupBrowser gets disconnected (for example when Puppeteer emits a “Browser disconnected” event). In this case, calling Client.destroy() can hang indefinitely. The promise returned by the function never resolves or rejects, so any cleanup code after await client.destroy() is never executed.

Expected Behavior

  • Client.destroy() should always resolve or reject within a bounded time.
  • Even if the browser is disconnected, authStrategy.destroy() should still run.
  • Application code should be able to continue cleanup after destroy().

Steps to Reproduce the Bug or Issue

  1. Launch a Client and authenticate (e.g., with RemoteAuth).
  2. Wait until it reaches the ready state.
  3. Cause Puppeteer to emit “Browser disconnected” (e.g., due to an unexpected browser shutdown).
  4. Call client.destroy().
  5. Observe that the call never returns.

// Example

await client.destroy();
console.log("cleanup finished"); // never reached

WhatsApp Account Type

Standard

Browser Type

Google Chrome

Operation System Type

Windows

Phone OS Type

Android

WhatsApp-Web.js Version

1.34.1

WhatsApp Web Version

2.3000.1027807705

Node.js Version

20.19.4

Authentication Strategy

LocalAuth

Additional Context

Analysis

When the Puppeteer Browser is already disconnected, the call to this.pupBrowser.close() may never resolve nor reject. This leaves Client.destroy() pending forever. Since it doesn’t throw, the caller sees neither error nor continuation, and cleanup never happens.

Proposed Fix

Make Client.destroy() resilient to a disconnected browser:

Client.prototype.destroy = async function () {
  const browser = this.pupBrowser;
  const isConnected = browser?.isConnected?.();
  if (isConnected) {
    await browser. Close();
  }
  await this.authStrategy.destroy();
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions