{"record":{"id":"e36c491540d8b1ee","repo":"paperclipai/paperclip","slug":"paperclip-runner-attachment-staging-count-denied","errorCode":"paperclip_runner_attachment_staging_count_denied","errorMessage":"paperclip_runner_attachment_staging_count_denied","messagePattern":"paperclip_runner_attachment_staging_count_denied","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/native-runtime/native-runner-file-handoff.ts","lineNumber":875,"sourceCode":"    )\n  ) {\n    throw new Error(\"paperclip_runner_attachment_staging_not_authorized\");\n  }\n  const reviewContext = readNativeReviewAssignmentContext(run.contextSnapshot);\n  const nativeReview = reviewContext\n    ? await getNativeReviewAssignment(input.db, {\n        companyId: input.binding.companyId,\n        issueId: input.binding.issueId,\n        agentId: input.binding.agentId,\n        contextSnapshot: reviewContext,\n      })\n    : null;\n  if (run.assigneeAgentId !== input.binding.agentId && !nativeReview) {\n    throw new Error(\"paperclip_runner_attachment_staging_not_authorized\");\n  }\n  const selections = wakeAttachmentSelections(run.contextSnapshot);\n  if (selections.length > MAX_NATIVE_STAGED_ATTACHMENTS) {\n    throw new Error(\"paperclip_runner_attachment_staging_count_denied\");\n  }\n  const workspaceRoot =\n    input.binding.executionTargetKind === \"local\"\n      ? await realpath(input.binding.workspaceRoot)\n      : null;\n  let releaseActiveStage = () => undefined;\n  let stagingDestinations: string[] = [];\n  if (workspaceRoot) {\n    const processDirectoryName = await currentStagingProcessDirectoryName();\n    await withStagingRegistryLock(workspaceRoot, async () => {\n      const stagingDirectory = await ensurePrivateStagingDirectory(\n        workspaceRoot,\n        processDirectoryName,\n      );\n      const activePaths =\n        activeStagingPathsByWorkspace.get(workspaceRoot) ?? new Set<string>();\n      const reusablePaths = await scrubNativeRunnerStagingResidue(\n        workspaceRoot,","sourceCodeStart":857,"sourceCodeEnd":893,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/native-runtime/native-runner-file-handoff.ts#L857-L893","documentation":"Thrown when the wake attachment selections captured in the run's contextSnapshot exceed MAX_NATIVE_STAGED_ATTACHMENTS. The handoff refuses to stage more attachments than the hard cap allows, protecting the local workspace staging directory from unbounded writes.","triggerScenarios":"A wake request with more than the maximum number of attachment selections stored in heartbeatRuns.contextSnapshot, then stageNativeRunnerWakeAttachments is called for that run while it is queued/running and authorized.","commonSituations":"A user attaching a very large batch of files to wake comments; a client bug accumulating duplicate selections in the snapshot across retries; an older runner snapshot format that did not enforce the client-side limit now being staged by newer server code.","solutions":["Reduce the number of selected attachments in the wake request to at most MAX_NATIVE_STAGED_ATTACHMENTS and re-issue the wake","Inspect run.contextSnapshot's wake attachment selections and prune duplicates before re-triggering the run","If the batch is legitimately large, split the work across multiple wake runs, each under the cap"],"exampleFix":"// before\nawait stageNativeRunnerWakeAttachments({ db, binding }); // 25 selections, cap exceeded\n// after\nconst MAX = 10;\nconst trimmed = selections.slice(0, MAX); // enforce cap client-side before staging\nawait updateRunSelections(db, runId, trimmed);\nawait stageNativeRunnerWakeAttachments({ db, binding });","handlingStrategy":"validation","validationCode":"const MAX = 10; // keep in sync with MAX_NATIVE_STAGED_ATTACHMENTS\nconst selections = wakeAttachmentSelections(run.contextSnapshot);\nif (selections.length > MAX) throw new Error(`too many wake attachments: ${selections.length} > ${MAX}`);","typeGuard":"null","tryCatchPattern":"try {\n  await stageNativeRunnerWakeAttachments({ db, binding });\n} catch (err) {\n  if (err instanceof Error && err.message === \"paperclip_runner_attachment_staging_count_denied\") {\n    // trim selections to the cap and resubmit the wake\n  } else throw err;\n}","preventionTips":["Enforce the attachment cap in the wake UI/CLI before selections reach the run snapshot","Deduplicate selections when accumulating across wake retries","Split very large attachment batches across multiple runs","Keep client-side cap constant synchronized with MAX_NATIVE_STAGED_ATTACHMENTS"],"tags":["attachments","limit-exceeded","native-runtime","validation"],"backgroundTag":"value-out-of-range","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T06:17:15.046Z"}