paperclipai/paperclip · error · ToolGatewayHttpError

run_context_mismatch

run_context_mismatch

Error message

Supplied run context does not match stored heartbeat context

What it means

Guard in the tool gateway run-context check: the companyId/agentId supplied with the gateway request do not match the heartbeat run stored for that runId, or the run is not in an active gateway status. It fires when a client reuses a runId belonging to a different company/agent or after the run finished, protecting against cross-tenant or stale-session tool execution.

Solutions

  1. Supply the same run context (runId, etc.) that was stored at heartbeat/session creation; do not mix contexts from different runs.
Defensive patterns

Strategy: validation

When it happens

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

Common situations: See trigger scenarios.


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

Appendix: source

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

        403,
        "Run does not belong to agent",
        "run_agent_mismatch",
      );
    }
    if (!ACTIVE_GATEWAY_RUN_STATUSES.has(run.status)) {
      throw new ToolGatewayHttpError(403, "Run is not active", "run_inactive");
    }

    const snapshot = asRecord(run.contextSnapshot);
    const snapshotIssueId = stringValue(snapshot?.issueId);
    const snapshotProjectId = stringValue(snapshot?.projectId);
    if (
      (input.issueId && snapshotIssueId && input.issueId !== snapshotIssueId) ||
      (input.projectId &&
        snapshotProjectId &&
        input.projectId !== snapshotProjectId)
    ) {
      throw new ToolGatewayHttpError(
        403,
        "Supplied run context does not match stored heartbeat context",
        "run_context_mismatch",
      );
    }
    const issueId = snapshotIssueId ?? input.issueId ?? null;
    let projectId = snapshotProjectId ?? input.projectId ?? null;
    if (issueId) {
      const [issue] = await db
        .select({ companyId: issues.companyId, projectId: issues.projectId })
        .from(issues)
        .where(eq(issues.id, issueId))
        .limit(1);
      if (!issue || issue.companyId !== input.companyId) {
        throw new ToolGatewayHttpError(
          403,
          "Issue context is outside the run company",
          "run_context_mismatch",

View on GitHub (pinned to 3f1d897a7c)