{"record":{"id":"51b76141c7070b9f","repo":"paperclipai/paperclip","slug":"retry-was-skipped-agents","errorCode":null,"errorMessage":"Retry was skipped.","messagePattern":"Retry was skipped\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"ui/src/api/agents.ts","lineNumber":271,"sourceCode":"  ) => {\n    const result = await api.post<\n      AgentWakeupResponse | ChatFailedRunRetryResponse\n    >(agentPath(id, companyId, \"/wakeup\"), {\n      source: \"on_demand\",\n      triggerDetail: \"manual\",\n      reason: \"retry_failed_run\",\n      failedRunId,\n    });\n    if (\"id\" in result) return { runId: result.id, issueId: null };\n    if (\"actionId\" in result) {\n      if (result.status === \"failed\" || result.status === \"cancelled\") {\n        throw new Error(\n          \"This retry could not start. Open the task to review its current access and recovery state.\",\n        );\n      }\n      return { runId: result.runId, issueId: result.issueId };\n    }\n    throw new Error(result.message ?? \"Retry was skipped.\");\n  },\n  loginWithClaude: (id: string, companyId?: string) =>\n    api.post<ClaudeLoginResult>(agentPath(id, companyId, \"/claude-login\"), {}),\n  startAdapterAuthLogin: (\n    companyId: string,\n    type: string,\n    data: { environmentId: string; ttlSeconds?: number; aiConnection?: import(\"@paperclipai/shared\").AiConnectionLoginIntent },\n  ) =>\n    api.post<AdapterAuthSessionResponse>(\n      `/companies/${encodeURIComponent(companyId)}/adapters/${encodeURIComponent(type)}/login-sessions`,\n      data,\n    ),\n  // The owner response repeats the live prompt on every read while the\n  // session holds an active public status, so this polling call carries the\n  // same no-store request option as the active-session read below.\n  getAdapterAuthLoginStatus: (companyId: string, type: string, sessionId: string) =>\n    api.get<AdapterAuthSessionOwnerResponse>(\n      `/companies/${encodeURIComponent(companyId)}/adapters/${encodeURIComponent(type)}/login-sessions/${encodeURIComponent(sessionId)}`,","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/ui/src/api/agents.ts#L253-L289","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check result.message first — the code already prefers it; surface it to the user instead of the generic fallback.","Verify the server's retry endpoint response shape matches the shared API contract (packages/shared types).","Confirm the agent/run supports retrying (check run status server-side) before calling retry.","Log the raw response body to diagnose the unexpected shape."],"exampleFix":"// before\nthrow new Error(result.message ?? \"Retry was skipped.\");\n// after\nif (!result.message) console.error(\"unexpected retry response\", result);\nthrow new Error(result.message ?? `Retry was skipped (status: ${result.status ?? \"unknown\"}).`);","handlingStrategy":"type-guard","validationCode":"// validate server contract in tests\nexpect(retryResponseSchema.safeParse(result).success).toBe(true); // id | actionId | message required","typeGuard":"function isRetryResult(r: unknown): r is { id?: string; actionId?: string; runId?: string; issueId?: string; message?: string } {\n  return typeof r === \"object\" && r !== null && (\"id\" in r || \"actionId\" in r || \"message\" in r);\n}","tryCatchPattern":"const result = await retryResponse.json();\nif (!isRetryResult(result)) {\n  console.error(\"unexpected retry response\", result);\n  throw new Error(\"Retry was skipped: unrecognized server response.\");\n}","preventionTips":["Keep ui API clients and shared validators in sync with the server retry endpoint contract.","Log raw response bodies for any retry response missing id/actionId to catch server drift fast.","Pin server and UI versions together during upgrades to avoid response-shape mismatch."],"tags":["ui","retry","unexpected-response"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"3f1d897a7c018d76563a21c6e39c3c9b03933622","analyzedAt":"2026-09-18T08:03:59.046Z","contentChangedAt":"2026-09-18T08:03:59.046Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}