paperclipai/paperclip · warning · Error

Retry was skipped.

Error message

Retry was skipped.

What it means

Fallback thrown by retryFailedRun when the retry API response has neither "id", "actionId", nor a "message" field — an unexpected/empty response shape from the server. "Retry was skipped." signals the server declined the retry without a structured result.

Solutions

  1. Check result.message first — the code already prefers it; surface it to the user instead of the generic fallback.
  2. Verify the server's retry endpoint response shape matches the shared API contract (packages/shared types).
  3. Confirm the agent/run supports retrying (check run status server-side) before calling retry.
  4. Log the raw response body to diagnose the unexpected shape.

Example fix

// before
throw new Error(result.message ?? "Retry was skipped.");
// after
if (!result.message) console.error("unexpected retry response", result);
throw new Error(result.message ?? `Retry was skipped (status: ${result.status ?? "unknown"}).`);
Defensive patterns

Strategy: type-guard

Validate before calling

// validate server contract in tests
expect(retryResponseSchema.safeParse(result).success).toBe(true); // id | actionId | message required

Type guard

function isRetryResult(r: unknown): r is { id?: string; actionId?: string; runId?: string; issueId?: string; message?: string } {
  return typeof r === "object" && r !== null && ("id" in r || "actionId" in r || "message" in r);
}

Try / catch

const result = await retryResponse.json();
if (!isRetryResult(result)) {
  console.error("unexpected retry response", result);
  throw new Error("Retry was skipped: unrecognized server response.");
}

Prevention

When it happens

Trigger: POST {agentPath}/retry returns a body lacking id/actionId — e.g. server responds with {status:"skipped"} or an error body the client does not recognize, or the endpoint shape drifted from the shared API contract.

Common situations: Server/client version mismatch after an upgrade; server returned an error envelope the client didn't anticipate; retry attempted on an agent type that doesn't support run retrying.

Understand the failure class

Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at ui/src/api/agents.ts:271

  ) => {
    const result = await api.post<
      AgentWakeupResponse | ChatFailedRunRetryResponse
    >(agentPath(id, companyId, "/wakeup"), {
      source: "on_demand",
      triggerDetail: "manual",
      reason: "retry_failed_run",
      failedRunId,
    });
    if ("id" in result) return { runId: result.id, issueId: null };
    if ("actionId" in result) {
      if (result.status === "failed" || result.status === "cancelled") {
        throw new Error(
          "This retry could not start. Open the task to review its current access and recovery state.",
        );
      }
      return { runId: result.runId, issueId: result.issueId };
    }
    throw new Error(result.message ?? "Retry was skipped.");
  },
  loginWithClaude: (id: string, companyId?: string) =>
    api.post<ClaudeLoginResult>(agentPath(id, companyId, "/claude-login"), {}),
  startAdapterAuthLogin: (
    companyId: string,
    type: string,
    data: { environmentId: string; ttlSeconds?: number; aiConnection?: import("@paperclipai/shared").AiConnectionLoginIntent },
  ) =>
    api.post<AdapterAuthSessionResponse>(
      `/companies/${encodeURIComponent(companyId)}/adapters/${encodeURIComponent(type)}/login-sessions`,
      data,
    ),
  // The owner response repeats the live prompt on every read while the
  // session holds an active public status, so this polling call carries the
  // same no-store request option as the active-session read below.
  getAdapterAuthLoginStatus: (companyId: string, type: string, sessionId: string) =>
    api.get<AdapterAuthSessionOwnerResponse>(
      `/companies/${encodeURIComponent(companyId)}/adapters/${encodeURIComponent(type)}/login-sessions/${encodeURIComponent(sessionId)}`,

View on GitHub (pinned to 3f1d897a7c)