paperclipai/paperclip · error · AuthorizationError

listener_ownership_mismatch

listener_ownership_mismatch

Error message

runtime id does not match lease

What it means

AuthorizationError from authorizeRemoval: a lease matching the handle was found, but the requesting runtime's UUID differs from the runtime bound at expose time. Enforces runtime isolation — runtime A can never remove runtime B's listener even with a leaked handle.

Source

Thrown at packages/tailscale-https-broker/src/authorization.ts:81

  return timingSafeEqual(ab, bb);
}

/**
 * Resolve the lease a `remove` request is authorized to act on. Requires an
 * exact handle match AND that the requesting peer + runtime UUID match the
 * lease bound at expose time. Runtime A can never remove runtime B's listener.
 */
export function authorizeRemoval(
  leases: readonly LeaseRecord[],
  request: { runtimeId: string; handle: string },
  peer: PeerCredentials,
): LeaseRecord {
  const lease = leases.find((entry) => handlesEqual(entry.handle, request.handle));
  if (!lease) {
    throw new AuthorizationError("invalid_handle", "unknown or stale lease handle");
  }
  if (lease.runtimeId !== request.runtimeId) {
    throw new AuthorizationError("listener_ownership_mismatch", "runtime id does not match lease");
  }
  if (lease.peerUid !== peer.uid || lease.peerGid !== peer.gid) {
    throw new AuthorizationError("listener_ownership_mismatch", "peer identity does not match lease");
  }
  return lease;
}

View on GitHub (pinned to 120ae5428f)

Solutions

  1. Use the runtime id that owns the lease, or acquire a fresh lease for this runtime.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at packages/tailscale-https-broker/src/authorization.ts:81 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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