paperclipai/paperclip · error

Status-only recovery runs cannot create or modify approvals

Error message

Status-only recovery runs cannot create or modify approvals

What it means

Permission guard assertApprovalMutationAllowedByRunContext: an agent actor whose run is a status-only recovery run (per its contextSnapshot) may not create or modify approvals, so the guard throws/returns an error response. It fires when a recovery run's agent attempts approval mutations — reserved for normal runs with full approval authority.

Source

Thrown at server/src/routes/approvals.ts:193

  async function assertApprovalMutationAllowedByRunContext(req: Request, res: any, companyId: string) {
    if (req.actor.type !== "agent") return true;
    const runId = req.actor.runId?.trim();
    if (!runId || !req.actor.agentId) return true;

    const run = await db
      .select({
        id: heartbeatRuns.id,
        companyId: heartbeatRuns.companyId,
        agentId: heartbeatRuns.agentId,
        contextSnapshot: heartbeatRuns.contextSnapshot,
      })
      .from(heartbeatRuns)
      .where(eq(heartbeatRuns.id, runId))
      .then((rows) => rows[0] ?? null);
    if (!run || run.companyId !== companyId || run.agentId !== req.actor.agentId) return true;
    if (!isStatusOnlyRecoveryContext(run.contextSnapshot)) return true;

    res.status(403).json({
      error: "Status-only recovery runs cannot create or modify approvals",
      details: {
        companyId,
        runId: run.id,
        recoveryIntent: "status_only",
        resumeRequiresNormalModel: true,
      },
    });
    return false;
  }

  router.get("/companies/:companyId/approvals", async (req, res) => {
    const companyId = req.params.companyId as string;
    assertCompanyAccess(req, companyId);
    if (!(await assertApprovalAccessAllowed(req, res, companyId))) return;
    const status = req.query.status as string | undefined;
    const result = await svc.list(companyId, status);
    res.json(result.map((approval) => redactApprovalPayload(approval)));

View on GitHub (pinned to 5716fe907e)

Solutions

  1. Retry the approval mutation from a normal (non-recovery) run or from board/operator context.
  2. Downgrade the recovery run to status-only actions; request a human or a regular run to handle the approval.
  3. Verify req.actor.runId/contextSnapshot classification is correct if the run is not intended to be status-only.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/routes/approvals.ts:193 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@5716fe907e (2026-09-02). Data as JSON: /api/errors/f5e9374eecee768b. Report an issue: GitHub.