{"record":{"id":"83b0a799179f905d","repo":"paperclipai/paperclip","slug":"paperclip-runner-file-handoff-not-authorized","errorCode":"paperclip_runner_file_handoff_not_authorized","errorMessage":"paperclip_runner_file_handoff_not_authorized","messagePattern":"paperclip_runner_file_handoff_not_authorized","errorType":"error_code","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/services/native-runtime/native-runner-file-handoff.ts","lineNumber":1127,"sourceCode":"        eq(heartbeatRuns.runtimeMode, \"native\"),\n        eq(heartbeatRuns.status, \"running\"),\n        eq(issues.id, binding.issueId),\n        eq(issues.companyId, binding.companyId),\n        eq(issues.assigneeAgentId, binding.agentId),\n        eq(issues.executionRunId, binding.runId),\n        eq(agents.id, binding.agentId),\n        eq(agents.companyId, binding.companyId),\n      ),\n    )\n    .for(\"update\")\n    .limit(1);\n  if (\n    !context ||\n    [\"paused\", \"terminated\", \"pending_approval\", \"error\"].includes(\n      context.agent.status,\n    )\n  ) {\n    throw new Error(\"paperclip_runner_file_handoff_not_authorized\");\n  }\n  return { statusVersion: context.issue.statusVersion };\n}\n\nexport async function prepareNativeRunnerFileHandoff(input: {\n  readonly db: Db;\n  readonly binding: NativeRunnerFileHandoffBinding;\n  readonly deliverable: NativeRunnerFileHandoffInput;\n  readonly storage?: StorageService;\n}): Promise<PreparedNativeRunnerFileHandoff> {\n  const { statusVersion } = await assertCurrentBinding(input.db, input.binding);\n  const verified = await readVerifiedWorkspaceFile(\n    input.binding,\n    input.deliverable,\n  );\n\n  const [existing] = await input.db\n    .select({","sourceCodeStart":1109,"sourceCodeEnd":1145,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/server/src/services/native-runtime/native-runner-file-handoff.ts#L1109-L1145","documentation":"Thrown by the file-handoff authorization check when there is no agent execution context, or the agent's status is one of paused, terminated, pending_approval, or error. A file handoff to the native runner is only allowed for agents in an active state, so handoff preparation is refused otherwise.","triggerScenarios":"Calling prepareNativeRunnerFileHandoff (or its underlying authorization helper) when the loaded agent context is null/undefined, or context.agent.status is exactly \"paused\", \"terminated\", \"pending_approval\", or \"error\".","commonSituations":"Requesting a file handoff after an operator paused the agent; retrying handoff after a previous run errored or the agent was terminated; hitting the handoff path while the run is blocked awaiting approval; passing a bad identifier so the context lookup returns nothing.","solutions":["Check the agent's current status and resume/reactivate it (clear paused/error, complete approval) before requesting the file handoff","Re-issue the handoff after the pending approval is granted","Verify the identifier used to load the agent context is correct so the context is not null","If termination was intentional, start a new run instead of handing off files to the terminated agent"],"exampleFix":"// before\nawait prepareNativeRunnerFileHandoff({ db, context }); // agent paused\n// after\nif (context && !\"paused terminated pending_approval error\".split(\" \").includes(context.agent.status)) {\n  await prepareNativeRunnerFileHandoff({ db, context });\n} else {\n  throw new Error(`handoff blocked: agent status is ${context?.agent.status ?? \"unknown\"}`);\n}","handlingStrategy":"try-catch","validationCode":"const status = context?.agent.status;\nconst handoffAllowed = !!context && ![\"paused\", \"terminated\", \"pending_approval\", \"error\"].includes(status);","typeGuard":"function handoffReady(c: { agent: { status: string } } | null | undefined): c is { agent: { status: \"queued\" | \"running\" } } {\n  return !!c && ![\"paused\", \"terminated\", \"pending_approval\", \"error\"].includes(c.agent.status);\n}","tryCatchPattern":"try {\n  await prepareNativeRunnerFileHandoff({ db, context });\n} catch (err) {\n  if (err instanceof Error && err.message === \"paperclip_runner_file_handoff_not_authorized\") {\n    // inspect context.agent.status, resume agent or await approval, then retry\n  } else throw err;\n}","preventionTips":["Check agent status before scheduling file handoffs; gate handoffs on active states only","Resolve pending approvals before requesting handoffs","Surface paused/terminated state in runner UI so operators re-enable agents proactively","Handle null context explicitly instead of passing an unresolved lookup result onward"],"tags":["authorization","agent-state","file-handoff","native-runtime"],"backgroundTag":"invalid-state-transition","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}