Skip to content

Race on first relay startup can hit EADDRINUSE on 127.0.0.1:19988 #75

Description

@georgeolaru

Summary

When two Playwriter CLI commands are started at nearly the same time while no relay server is running yet, both clients can decide the relay is down and both try to spawn it. One of the relay processes then crashes with EADDRINUSE on 127.0.0.1:19988.

After the relay is up, sequential Playwriter commands work normally. This looks like a first-start race rather than a general Chrome/extension connectivity problem.

Environment

  • playwriter: 0.0.89
  • Node: v22.22.0
  • OS: macOS 26.3.1 (25D771280a)
  • Chrome + extension connected locally

Repro

  1. Make sure no Playwriter relay server is running.
  2. Start two Playwriter CLI commands almost simultaneously in separate shells.
  3. For example:
    • playwriter session new
    • playwriter session list
  4. Observe that both commands can print startup messages as if they are each responsible for starting the relay.
  5. Check the relay log.

Observed

One relay instance starts successfully, while the other process crashes with:

Uncaught Exception: Error: listen EADDRINUSE: address already in use 127.0.0.1:19988
  code: 'EADDRINUSE'

Relevant local relay log excerpt:

CDP relay server started
CDP relay server started
Uncaught Exception: Error: listen EADDRINUSE: address already in use 127.0.0.1:19988
Extension connected (...)

In my case the CLI behavior during that race was inconsistent: one command eventually succeeded, another was still waiting on startup until the relay settled.

Expected

Concurrent first-use CLI calls should not race each other into spawning duplicate relay servers.

Possible acceptable behaviors:

  • only one client starts the relay and the other waits/retries
  • a second client sees the relay come up and reuses it
  • EADDRINUSE during startup is treated as "another client won the race" and the client retries the health/version check instead of surfacing a broken startup

Likely Cause

This looks like a TOCTOU race in relay startup. From local inspection, the client checks whether the relay is running and then spawns a detached server process, but there does not appear to be any inter-process lock/claim around that startup path.

I realize that's an inference from the installed package rather than a confirmed maintainer diagnosis, but it matches the observed behavior and log output.

If helpful, I can also provide a tiny shell repro that launches the two commands in parallel.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions