paperclipai/paperclip · error · ToolGatewayHttpError

approval_required

approval_required

Error message

Tool action requires approval

What it means

Approval-required flow: this helper builds the agent-facing instruction text returned with the 409/deferral when a governed tool call needs human approval. It resolves the issue identifier (falling back to the raw issueId) so the agent knows which task's approval card to wait on and to end its run in_review instead of retrying.

Source

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

    if (!allowedActions || allowedActions.includes(action)) return;
    await writeAudit({
      session,
      companyId: session.companyId,
      agentId: session.agentId,
      runId: session.runId,
      issueId: session.issueId,
      action: action.endsWith("/list") ? "tool_gateway.discovery" : "tool_gateway.call_denied",
      details: {
        decision: "deny",
        reasonCode: "gateway_token_action_denied",
        requestedAction: action,
        allowedActions,
      },
    });
    throw new ToolGatewayHttpError(403, "Gateway bearer token is not allowed to perform this MCP action", "gateway_token_action_denied", {
      requestedAction: action,
    });
  }

  async function writeToolCallEvent(input: {
    invocationId?: string | null;
    actionRequestId?: string | null;
    session: ToolGatewaySession;
    eventType: "policy_decision" | "invocation_created" | "approval_requested" | "approval_resolved" | "call_started" | "call_completed" | "call_failed" | "call_denied";
    outcome: "pending" | "success" | "failure" | "denied" | "timeout" | "cancelled";
    toolName: string;
    policyDecision?: "allow" | "deny" | "require_approval" | "defer_runtime" | null;
    reasonCode?: string | null;
    argumentsSummary?: ReturnType<typeof summarizeToolValue> | null;
    resultSummary?: ReturnType<typeof summarizeToolValue> | null;
    metadata?: Record<string, unknown> | null;
    tool?: ToolGatewayDescriptor | null;
  }) {
    const metadata = input.tool ? toolAuditMetadata(input.tool) : {};
    await db.insert(toolCallEvents).values({
      companyId: input.session.companyId,

View on GitHub (pinned to 01ad858492)

Solutions

  1. Request approval for the tool action (create an approval request) and wait for board approval before executing.
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at server/src/services/tool-gateway.ts:1483 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/9737cc51ac26ae09. Report an issue: GitHub.