{"record":{"id":"981eced35d416992","repo":"paperclipai/paperclip","slug":"resume-request-was-skipped","errorCode":null,"errorMessage":"Resume request was skipped.","messagePattern":"Resume request was skipped\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"ui/src/pages/AgentDetail.production.tsx","lineNumber":3294,"sourceCode":"    const taskId = asNonEmptyString(context.taskId);\n    const taskKey = asNonEmptyString(context.taskKey);\n    const commentId = asNonEmptyString(context.wakeCommentId) ?? asNonEmptyString(context.commentId);\n    if (issueId) payload.issueId = issueId;\n    if (taskId) payload.taskId = taskId;\n    if (taskKey) payload.taskKey = taskKey;\n    if (commentId) payload.commentId = commentId;\n    return payload;\n  }, [run.contextSnapshot, run.id]);\n  const resumeRun = useMutation({\n    mutationFn: async () => {\n      const result = await agentsApi.wakeup(run.agentId, {\n        source: \"on_demand\",\n        triggerDetail: \"manual\",\n        reason: \"resume_process_lost_run\",\n        payload: resumePayload,\n      }, run.companyId);\n      if (!(\"id\" in result)) {\n        throw new Error(result.message ?? \"Resume request was skipped.\");\n      }\n      return result;\n    },\n    onSuccess: (resumedRun) => {\n      queryClient.invalidateQueries({ queryKey: queryKeys.heartbeats(run.companyId, run.agentId) });\n      navigate(`/agents/${agentRouteId}/runs/${resumedRun.id}`);\n    },\n  });\n\n  const canRetryRun = run.status === \"failed\" || run.status === \"timed_out\";\n  const retryPayload = useMemo(() => {\n    const payload: Record<string, unknown> = {};\n    const context = asRecord(run.contextSnapshot);\n    if (!context) return payload;\n    const issueId = asNonEmptyString(context.issueId);\n    const taskId = asNonEmptyString(context.taskId);\n    const taskKey = asNonEmptyString(context.taskKey);\n    if (issueId) payload.issueId = issueId;","sourceCodeStart":3276,"sourceCodeEnd":3312,"githubUrl":"https://github.com/paperclipai/paperclip/blob/01ad8584922b5d85292b1723cae71fa0d9b07a19/ui/src/pages/AgentDetail.production.tsx#L3276-L3312","documentation":"After calling agentsApi.wakeup to resume a run whose process was lost, the code checks whether the response looks like a run (has an \"id\"). If it does not, the API declined to resume and returned only a message; this error is thrown with the server-provided message, defaulting to \"Resume request was skipped.\" It surfaces a server-side skip decision (e.g. guard rails in the wakeup handler) to the UI.","triggerScenarios":"agentsApi.wakeup(..., { reason: \"resume_process_lost_run\", ... }) resolves with a payload lacking an \"id\" field — the backend skipped the wakeup (e.g. run no longer eligible, agent busy, stale run) and returned { message: ... } or a non-run object.","commonSituations":"The run was concurrently picked up or cancelled elsewhere; the agent has a max-concurrency or pause gate blocking on_demand wakeups; the run record transitioned between page load and the resume click; backend validation rejects the resume but returns 200 with a message.","solutions":["Read the accompanying server message (result.message) for the concrete skip reason and address it.","Refresh the run/heartbeat data and retry the resume if the state was stale.","Check agent pause/concurrency/budget gates in the UI and lift them before resuming.","Inspect server logs for the wakeup handler's skip branch to confirm why no run was created."],"exampleFix":"// before\nif (!(\"id\" in result)) {\n  throw new Error(result.message ?? \"Resume request was skipped.\");\n}\n// after (caller-side narrowing before throwing)\nif (!(\"id\" in result)) {\n  toast.error(result.message ?? \"Resume request was skipped.\");\n  await queryClient.invalidateQueries({ queryKey: queryKeys.heartbeats(run.companyId, run.agentId) });\n  return;\n}","handlingStrategy":"type-guard","validationCode":"// nothing to validate client-side pre-call; refresh run state first\nawait queryClient.invalidateQueries({ queryKey: queryKeys.heartbeats(companyId, agentId) });","typeGuard":"const isResumedRun = (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  const run = await resumeRun.mutateAsync();\n  navigate(`/agents/${agentRouteId}/runs/${run.id}`);\n} catch (e) {\n  toast.error(e.message);\n  await queryClient.invalidateQueries({ queryKey: queryKeys.heartbeats(companyId, agentId) });\n}","preventionTips":["Refresh heartbeat/run state before offering the Resume action.","Check agent pause/budget/concurrency status and disable Resume when gated.","Render the server's skip message (result.message) rather than a generic failure."],"tags":["ui","api-response","resume","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"}