{"record":{"id":"dc7be33a48225bf8","repo":"paperclipai/paperclip","slug":"retry-was-skipped-dc7be3","errorCode":null,"errorMessage":"Retry was skipped.","messagePattern":"Retry was skipped\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui/src/pages/IssueDetail.tsx","lineNumber":1522,"sourceCode":"  });\n  const resolvedActivity = activity ?? [];\n  const resolvedLinkedRuns = linkedRuns ?? [];\n  const retryFailedRun = useMutation({\n    mutationFn: async (runId: string) => {\n      const failedRun = resolvedLinkedRuns.find((run) => run.runId === runId);\n      if (!failedRun) throw new Error(\"Failed run is no longer available.\");\n      const result = await agentsApi.wakeup(\n        failedRun.agentId,\n        {\n          source: \"on_demand\",\n          triggerDetail: \"manual\",\n          reason: \"retry_failed_run\",\n          payload: { issueId },\n        },\n        companyId,\n      );\n      if (!(\"id\" in result)) {\n        throw new Error(result.message ?? \"Retry was skipped.\");\n      }\n      return result;\n    },\n    onSuccess: () => {\n      queryClient.invalidateQueries({\n        queryKey: queryKeys.issues.runs(issueId),\n      });\n      queryClient.invalidateQueries({\n        queryKey: queryKeys.issues.liveRuns(issueId),\n      });\n      queryClient.invalidateQueries({\n        queryKey: queryKeys.issues.activeRun(issueId),\n      });\n    },\n    onError: (error) => {\n      pushToast({\n        title: \"Run retry failed\",\n        body: error instanceof Error ? error.message : \"Unable to retry run\",","sourceCodeStart":1504,"sourceCodeEnd":1540,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/ui/src/pages/IssueDetail.tsx#L1504-L1540","documentation":"Same wakeup-response guard as the AgentDetail retry path, applied in IssueDetail: agentsApi.wakeup with reason \"retry_failed_run\" must return an object containing \"id\" (the new run). A response without id means the server skipped the retry, so this error is thrown, preferring the server's message. It exposes a soft server-side skip to the mutation's error state.","triggerScenarios":"agentsApi.wakeup(agentId, { reason: \"retry_failed_run\", payload: { issueId } }, companyId) resolves with a payload lacking \"id\" — the backend declined to create a retry run and returned only a message or non-run shape.","commonSituations":"The agent is paused, over budget, or at concurrency limits so on_demand wakeups are rejected; the failed run changed state concurrently; backend validation rejects the issue-linked retry payload.","solutions":["Check result.message for the skip reason (pause/budget/concurrency) and resolve it.","Refresh issue runs and the agent's status, then Retry again.","Unpause the agent or clear budget/concurrency gates before retrying.","Check server logs for the wakeup skip branch to confirm the exact guard hit."],"exampleFix":"// before\nif (!(\"id\" in result)) {\n  throw new Error(result.message ?? \"Retry was skipped.\");\n}\n// after\nif (!(\"id\" in result)) {\n  toast.error(result.message ?? \"Retry was skipped.\");\n  return null;\n}","handlingStrategy":"type-guard","validationCode":"// check agent gates before offering Retry\nconst canRetry = !agent.paused && !agent.budgetExceeded;","typeGuard":"const isNewRun = (r: unknown): r is { id: string } =>\n  typeof r === \"object\" && r !== null && \"id\" in r && typeof (r as { id: unknown }).id === \"string\";","tryCatchPattern":"try {\n  await retryFailedRun.mutateAsync(runId);\n} catch (e) {\n  toast.error(e.message);\n  await queryClient.invalidateQueries({ queryKey: queryKeys.issues.runs(issueId) });\n}","preventionTips":["Check agent pause/budget/concurrency state before showing Retry.","Refresh the issue's run list before retrying from a stale view.","Prefer the server's message in the toast so users learn the actual skip reason."],"tags":["ui","api-response","retry","run-lifecycle"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"01ad8584922b5d85292b1723cae71fa0d9b07a19","analyzedAt":"2026-09-10T03:14:50.855Z","contentChangedAt":"2026-09-10T03:14:50.855Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}