paperclipai/paperclip · error

service process exited after losing its allocated port

Error message

service process exited after losing its allocated port

What it means

During the port-bind wait, a listener appeared on the allocated port but then the child process exited after losing ownership of it — the port ended up held by another process. Reported as a collision-style failure of the service start.

Source

Thrown at server/src/services/workspace-runtime.ts:4825

  child: ChildProcess;
}) {
  const deadline = Date.now() + resolveWorkspaceRuntimeReadinessTimeoutSec(input.service) * 1000;
  while (Date.now() < deadline) {
    if (input.child.exitCode !== null || input.child.signalCode !== null) {
      throw new Error("service process exited before binding its allocated port");
    }

    const ownerPid = await readLocalServicePortOwner(input.port);
    if (ownerPid) {
      const childPid = input.child.pid ?? null;
      if (!childPid || !(await isLocalServiceProcessOwnedBy(ownerPid, childPid))) {
        throw new RuntimeServicePortBindCollision(input.port);
      }
      // Require the same launched process group to retain ownership across a stability delay.
      // Cwd matching alone is insufficient because sibling services can share a workspace.
      await delay(250);
      if (input.child.exitCode !== null || input.child.signalCode !== null) {
        throw new Error("service process exited after losing its allocated port");
      }
      const stableOwnerPid = await readLocalServicePortOwner(input.port);
      if (!stableOwnerPid || !(await isLocalServiceProcessOwnedBy(stableOwnerPid, childPid))) {
        throw new RuntimeServicePortBindCollision(input.port);
      }
      return;
    }

    // A present listener proves only that some listener appeared. If listener ownership cannot
    // be attributed to this child after a stability delay, retry instead of accepting a sibling.
    // The presence read never binds the port, so it cannot steal the port from the child.
    if (await hasLoopbackPortListener(input.port)) {
      await delay(250);
      if (input.child.exitCode !== null || input.child.signalCode !== null) {
        throw new Error("service process exited after losing its allocated port");
      }
      const stableOwnerPid = await readLocalServicePortOwner(input.port);
      const childPid = input.child.pid ?? null;

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. Review the service logs for the crash after binding, fix the underlying error, and restart.
  2. Ensure no other process stole the port while the service was running.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at server/src/services/workspace-runtime.ts:4672 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@a7e689b3c3 (2026-08-18). Data as JSON: /api/errors/d65182da57f21355. Report an issue: GitHub.