{"record":{"id":"0ad9a5510c12bb8d","repo":"paperclipai/paperclip","slug":"acpx-pending-tool-limit-reached","errorCode":null,"errorMessage":"ACPX pending tool limit reached","messagePattern":"ACPX pending tool limit reached","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts","lineNumber":593,"sourceCode":"  } finally {\n    rejectTurnWaiters(currentTurnId, \"ACPX turn became terminal\");\n    if (turnId === currentTurnId) turnId = null;\n  }\n  // A terminal frame is also runnerd's permission to recycle this provider.\n  // Publish it only after no callback can inherit this turn's mutable binding.\n  emit(\"runtime.turn_terminal\", terminal, currentTurnId);\n}\n\nasync function waitForTool(call: RunnerToolCall): Promise<unknown> {\n  const activeTurnId = turnId;\n  if (!activeTurnId || call.signal.aborted) {\n    throw new Error(\"ACPX tool call is not bound to an active turn\");\n  }\n  const callId = boundedIdentity(call.callId, \"callId\");\n  if (tools.has(callId)) throw new Error(\"ACPX tool call is duplicated\");\n  const operationId = boundedIdentity(call.tool, \"operationId\");\n  if (tools.size >= MAX_PENDING_TOOLS) {\n    throw new Error(\"ACPX pending tool limit reached\");\n  }\n  if (\n    operationId === PRP_COMPLETION_TOOL_NAME ||\n    operationId === PRP_BLOCK_TOOL_NAME\n  ) {\n    const validation = validatePrpStructuredRunResult(call.arguments);\n    if (!validation.ok) {\n      throw new Error(\"ACPX semantic result failed PRP schema validation\");\n    }\n    const blocked = validation.result.reportedWorkDisposition === \"blocked\";\n    if (\n      (operationId === PRP_BLOCK_TOOL_NAME && !blocked) ||\n      (operationId === PRP_COMPLETION_TOOL_NAME && blocked)\n    ) {\n      throw new Error(\n        \"ACPX semantic result disposition does not match its terminal operation\",\n      );\n    }","sourceCodeStart":575,"sourceCodeEnd":611,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts#L575-L611","documentation":"Resource-cap guard in the ACPX runtime sidecar's waitForTool: the number of tool calls pending within the current turn exceeded the sidecar's bounded pending-tool limit, so further calls are rejected rather than growing an unbounded waiter map. Fires when a single provider turn fans out more concurrent tool calls than the configured cap — a backstop against runaway or malformed provider turns.","triggerScenarios":"Thrown at packages/paperclip-runner/src/cli/acpx-runtime-sidecar.ts:593 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Reduce the number of concurrent tool calls the agent issues per turn (serialize or batch them).","If the workload legitimately needs more parallel calls, raise the pending-tool limit in the sidecar configuration.","Check for a provider bug that leaks pending entries (calls that never settle) and drains the budget."],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}