paperclipai/paperclip · error · ToolGatewayHttpError

action_tool_mismatch

action_tool_mismatch

Error message

Approved action request is for a different tool

What it means

Replay consistency guard: the tool name on the stored invocation does not equal the tool the session is currently calling. The 409 action_tool_mismatch prevents replaying an approval granted for one tool against a different tool within the same session context.

Solutions

  1. Execute the approved action with the same tool it was approved for; tool substitution invalidates the approval.
Defensive patterns

Strategy: validation

When it happens

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

Common situations: See trigger scenarios.


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18). Data as JSON: /api/errors/8af41e8f76de33db. Report an issue: GitHub.

Appendix: source

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

        invocationId: invocation.id,
        toolName: invocation.toolName,
        ownsExecutingClaim: true,
      });
    }

    const argumentsSummary = validateToolContent({
      value: parameters,
      direction: "arguments",
      sensitiveMode: "redact",
      promptInjectionMode: "ignore",
    }).summary;
    // Final recheck at the last DB write before dispatch: tool and snapshot
    // resolution above involve network calls, so re-verify the issue is still
    // open now that only the provider call remains. A close that commits after
    // this read has raced an execution that was approved, claimed, and verified
    // while the issue was open; that instant is irreducible for an external
    // side effect gated by DB state (holding a DB lock across a remote provider
    // call is not an option), and the accepted linearization is that the
    // execution wins — its result still lands on the expired card via
    // reflectToolActionInteractionLifecycle.
    await assertIssueOpenForApprovedAction({ claimed, invocation });

    const startedAt = Date.now();
    await db
      .update(toolInvocations)
      .set({
        status: "executing",
        approvalState: "approved",
        startedAt: new Date(),
        updatedAt: new Date(),
      })
      .where(eq(toolInvocations.id, invocation.id));
    await reflectToolActionInteractionLifecycle({
      actionRequestId: claimed.id,
      status: "executing",
    });

View on GitHub (pinned to 3f1d897a7c)