paperclipai/paperclip · error · BridgeProcessCapacityError

The bridge host reached its reserved process body byte ceili

Error message

The bridge host reached its reserved process body byte ceiling. Retry later.

What it means

In the sandbox callback bridge, request body chunks are accumulated with a hard size check and incremental reservation on the shared processBodyLedger. This error is thrown when a chunk cannot be reserved because the host-wide reserved process body byte pool is exhausted (distinct from the hard 'exceeded the configured size limit' error for single oversized bodies).

Source

Thrown at packages/adapter-utils/src/sandbox-callback-bridge.ts:2256

// once, after the body is no longer needed, so its reserved bytes return to
// the ledger on completion, on an error the caller raises later, on a client
// abort, and on a timeout — every path funnels through the caller's own
// finally block. A read that fails here (the size limit, or a denied
// process reservation) releases its own partial reservation immediately, so
// no caller-side release call is needed for that path.
async function readBodyBytes(req) {
  const chunks = [];
  let totalBytes = 0;
  let reservedBytes = 0;
  try {
    for await (const chunk of req) {
      const nextChunk = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
      totalBytes += nextChunk.byteLength;
      if (totalBytes > maxBodyBytes) {
        throw new Error("Bridge request body exceeded the configured size limit.");
      }
      if (!processBodyLedger.reserve(nextChunk.byteLength)) {
        throw new BridgeProcessCapacityError();
      }
      reservedBytes += nextChunk.byteLength;
      chunks.push(nextChunk);
    }
    if (!processBodyLedger.reserve(totalBytes)) {
      throw new BridgeProcessCapacityError();
    }
    reservedBytes += totalBytes;
    const body = Buffer.concat(chunks);
    return { body, release: () => processBodyLedger.release(reservedBytes) };
  } catch (error) {
    processBodyLedger.release(reservedBytes);
    throw error;
  }
}

async function readBody(req) {
  const { body, release } = await readBodyBytes(req);

View on GitHub (pinned to 01ad858492)

Solutions

  1. Retry the callback request after a short delay; capacity returns when in-flight bodies complete.
  2. Ensure release() (which returns reservedBytes to the ledger) executes on all error paths for every request.
  3. Serialize or rate-limit sandbox callback requests to fit within the ledger ceiling.
  4. Increase the process body byte ceiling in the sandbox callback bridge configuration.

Example fix

// before
if (!processBodyLedger.reserve(nextChunk.byteLength)) {
  throw new BridgeProcessCapacityError();
}
// after
if (!processBodyLedger.reserve(nextChunk.byteLength)) {
  res.statusCode = 503; res.setHeader('retry-after', '2'); res.end();
  throw new BridgeProcessCapacityError();
}
Defensive patterns

Strategy: retry

Validate before calling

const cl = Number(req.headers["content-length"] ?? 0);
if (cl > maxBodyBytes) { res.statusCode = 413; res.end(); return; }
if (!processBodyLedger.canReserve(cl)) { res.statusCode = 503; res.setHeader("retry-after", "2"); res.end(); return; }

Type guard

null

Try / catch

try {
  const { body, release } = await reserveCallbackBody(req, ledger);
  try { handle(body); } finally { release(); }
} catch (err) {
  if (err instanceof BridgeProcessCapacityError) respond503RetryLater(res);
  else throw err;
}

Prevention

When it happens

Trigger: While reading a callback request body, processBodyLedger.reserve(nextChunk.byteLength) returns false for some chunk — total pool capacity is consumed by other concurrent bridge requests even though this body is under maxBodyBytes.

Common situations: Many sandbox callbacks arriving concurrently at one bridge host; a prior request leaked its reservation (release never ran); the pool ceiling configured below normal concurrency demands; a large in-flight body hogging capacity.

Related errors


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-09-10). Data as JSON: /api/errors/61cdbecbc17bf494. Report an issue: GitHub.