paperclipai/paperclip · error · ToolGatewayHttpError

formal_approval_required

formal_approval_required

Error message

Tool action request requires formal board approval before execution

What it means

Governance guard during approval resolution: the action request references a formal approvals row that is missing or not in approved status. The 409 formal_approval_required blocks execution until the board formally approves the linked approval record, since this action was configured to require formal approval.

Source

Thrown at server/src/services/tool-gateway.ts:5450

    const settled = await db.transaction(async (tx) => {
      // Lock in the same invocation -> request order used by the normal
      // execution settlement path. The claim timestamp is the ownership token:
      // a consumer that merely read an approved row cannot settle another
      // consumer's claim, and a pre-dispatch failure cannot overwrite a call
      // that has already entered provider execution or completed successfully.
      const [invocation] = await tx
        .select({ status: toolInvocations.status })
        .from(toolInvocations)
        .where(eq(toolInvocations.id, input.invocationId))
        .for("update")
        .limit(1);
      if (invocation?.status !== input.expectedInvocationStatus) return false;

      const [actionRequest] = await tx
        .select({ status: toolActionRequests.status, updatedAt: toolActionRequests.updatedAt })
        .from(toolActionRequests)
        .where(eq(toolActionRequests.id, input.actionRequestId))
        .for("update")
        .limit(1);
      if (
        actionRequest?.status !== "executing"
        || actionRequest.updatedAt.getTime() !== input.claimUpdatedAt.getTime()
      ) {
        return false;
      }

      await tx.update(toolInvocations).set({
        status: "failed",
        idempotencyKey: null,
        errorCode: reasonCode,
        errorMessage: message,
        completedAt: now,
        updatedAt: now,
      }).where(and(
        eq(toolInvocations.id, input.invocationId),
        eq(toolInvocations.status, input.expectedInvocationStatus),

View on GitHub (pinned to 01ad858492)

Solutions

  1. This action requires formal board approval; route it through the board approval flow instead of executing directly.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at server/src/services/tool-gateway.ts:5282 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@01ad858492 (2026-08-18). Data as JSON: /api/errors/38336dae0cec2619. Report an issue: GitHub.