Skip to content

HTTP/2 SIGABRT (is_write_in_progress assertion) in socksClientCertificatesInterceptor when TLS connection fails #41105

@pschroeder89

Description

@pschroeder89

Description

When clientCertificates is configured and a proxied TLS connection negotiates h2 then fails, the SOCKS MITM proxy in socksClientCertificatesInterceptor.ts crashes with:

Assertion failed: is_write_in_progress()
node::http2::Http2Session::OnStreamAfterWrite (node_http2.cc:1780)

Root Cause

In the h2 503 error response path, the stream cleanup can fire before the DATA write completes:

session.once("stream", (stream) => {
  const cleanup = (error) => {
    session.close();
    this._browserEncrypted.destroy(error);
  };
  stream.once("end", cleanup);    // may fire synchronously on GET requests
  stream.once("error", cleanup);
  stream.respond({ status: 503 });
  stream.end(responseBody);       // queues DATA write via setImmediate
});

For GET requests the client sends END_STREAM with HEADERS, so 'end' can fire synchronously BEFORE stream.end() is called. The cleanup listener then queues setImmediate(cleanup) before the DATA write's setImmediate:

  1. SI-CLEANUPcleanup()_browserEncrypted.destroy() → clears is_write_in_progress
  2. SI-DATAfinishWriteOnStreamAfterWriteCHECK(is_write_in_progress)SIGABRT

Workaround

Capture the 'end' listener without registering it. Wrap stream.end() to call origEnd() first (which synchronously queues SI-DATA), then queue setImmediate(runCleanup) as SI-CLEANUP. FIFO guarantees SI-DATA runs before SI-CLEANUP.

Reproduction

  • Configure clientCertificates in Playwright config
  • Run tests that make HTTPS requests to origins where TLS fails (e.g., cert mismatch)
  • The crash is intermittent — a race condition — but reproduces reliably under load (--repeat-each=100)

Environment

  • Playwright 1.60.0
  • Node.js 22.x
  • macOS / Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions