paperclipai/paperclip · error · ExposurePortOwnershipConflictError

exposure_port_ownership_conflict

exposure_port_ownership_conflict

Error message

HTTPS exposure allocation denied: ${describeExposurePortConflict(conflict)}

What it means

HTTPS exposure port-pair allocation was denied because a live conflict was found: a bound listener or published Serve mapping on the app/HMR port pair belongs to a different execution workspace. Cross-workspace ownership is terminal, never adopted.

Source

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

        reserved,
        preferredAppPort,
        claimPair: (candidate) => exposurePortPairClaims.claim(candidate),
      });
      claimed.push(pair);

      // Complete mediation before the broker is asked for anything: persisted
      // reservations were already folded into `reserved`, so what remains is the
      // live host — the listener actually bound, and the Serve mapping actually
      // published. Either one belonging to a different execution workspace is
      // terminal, never an adoption.
      const conflict = findExposurePairConflict({
        pair,
        claimant: input.claimant,
        ledger,
        listenerOwners: await readExposureListenerOwners([pair.appPort, pair.hmrPort]),
        serveMappingOwners,
      });
      if (conflict) throw new ExposurePortOwnershipConflictError(conflict);

      const result = await reserveExposure(workspaceRuntimeExposureDeps, {
        runtimeId: input.runtimeId,
        config: input.config,
        appPort: pair.appPort,
      });
      if (result.handle) {
        // Keep this pair's claim; the caller releases it on stop/teardown.
        claimed.pop();
        return { appPort: pair.appPort, hmrPort: pair.hmrPort, status: result.status, handle: result.handle };
      }
      if (!result.status.lastError || !retryable.has(result.status.lastError)) {
        throw new Error(`HTTPS exposure reservation failed: ${result.status.lastError ?? "unknown broker error"}`);
      }
      reserved.add(pair.appPort);
      reserved.add(pair.hmrPort);
      // The preference lost its race with a conflicting/manual/quarantined
      // mapping; drop it so the retry scans instead of re-offering the same port.

View on GitHub (pinned to a7e689b3c3)

Solutions

  1. The requested HTTPS exposure port conflicts with an existing allocation (details in the message). Choose a different port or release the conflicting allocation.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/services/workspace-runtime.ts:4157 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/8e30f3143e177d30. Report an issue: GitHub.