paperclipai/paperclip · error

Retry was skipped.

Error message

Retry was skipped.

What it means

Same guard as the resume path but for retrying a failed run: agentsApi.wakeup with reason "retry_failed_run" should return a new run object containing "id". If the server responds without an id, the retry was skipped server-side and this error is thrown, falling back to the server's message. It converts a soft skip response into a visible mutation error.

Source

Thrown at ui/src/pages/AgentDetail.production.tsx:3326

    if (!context) return payload;
    const issueId = asNonEmptyString(context.issueId);
    const taskId = asNonEmptyString(context.taskId);
    const taskKey = asNonEmptyString(context.taskKey);
    if (issueId) payload.issueId = issueId;
    if (taskId) payload.taskId = taskId;
    if (taskKey) payload.taskKey = taskKey;
    return payload;
  }, [run.contextSnapshot]);
  const retryRun = useMutation({
    mutationFn: async () => {
      const result = await agentsApi.wakeup(run.agentId, {
        source: "on_demand",
        triggerDetail: "manual",
        reason: "retry_failed_run",
        payload: retryPayload,
      }, run.companyId);
      if (!("id" in result)) {
        throw new Error(result.message ?? "Retry was skipped.");
      }
      return result;
    },
    onSuccess: (newRun) => {
      queryClient.invalidateQueries({ queryKey: queryKeys.heartbeats(run.companyId, run.agentId) });
      navigate(`/agents/${agentRouteId}/runs/${newRun.id}`);
    },
  });

  const { data: touchedIssues } = useQuery({
    queryKey: queryKeys.runIssues(run.id),
    queryFn: () => activityApi.issuesForRun(run.id),
  });
  const touchedIssueIds = useMemo(
    () => Array.from(new Set((touchedIssues ?? []).map((issue) => issue.issueId))),
    [touchedIssues],
  );

View on GitHub (pinned to 01ad858492)

Solutions

  1. Check result.message for the server's skip reason and fix that underlying cause (pause, budget, concurrency).
  2. Refresh heartbeats/run data and retry if the click acted on stale state.
  3. Unpause the agent or free budget/concurrency slots, then Retry again.
  4. Verify server logs for the wakeup skip branch for reason "retry_failed_run".

Example fix

// before
if (!("id" in result)) {
  throw new Error(result.message ?? "Retry was skipped.");
}
// after (caller-side handling)
if (!("id" in result)) {
  toast.error(result.message ?? "Retry was skipped — check that the agent is not paused.");
  return;
}
Defensive patterns

Strategy: type-guard

Validate before calling

// refresh run state before offering Retry
await queryClient.invalidateQueries({ queryKey: queryKeys.heartbeats(companyId, agentId) });

Type guard

const isNewRun = (r: unknown): r is { id: string } =>
  typeof r === "object" && r !== null && "id" in r && typeof (r as { id: unknown }).id === "string";

Try / catch

try {
  const newRun = await retryRun.mutateAsync();
  navigate(`/agents/${agentRouteId}/runs/${newRun.id}`);
} catch (e) {
  toast.error(e.message);
}

Prevention

When it happens

Trigger: agentsApi.wakeup(..., { reason: "retry_failed_run", ... }) resolves with an object lacking "id" — the backend refused to spawn the retry run and returned only a message or non-run shape.

Common situations: The failed run was already retried or deleted concurrently; the agent is paused or over budget so on_demand wakeups are rejected; the run's state changed between listing and clicking Retry; server validation rejects the payload.

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@01ad858492 (2026-09-10). Data as JSON: /api/errors/77f53dcbc97ac4ff. Report an issue: GitHub.