{"record":{"id":"1cf0bbdda3477ec1","repo":"paperclipai/paperclip","slug":"task-details-are-still-loading-please-try-again","errorCode":null,"errorMessage":"Task details are still loading. Please try again.","messagePattern":"Task details are still loading\\. Please try again\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"ui/src/pages/IssueDetail.tsx","lineNumber":5206,"sourceCode":"          queryKeys.issues.feedbackVotes(issueId!),\n          context.previousVotes,\n        );\n      }\n      pushToast({\n        title: \"Failed to save feedback\",\n        body: err instanceof Error ? err.message : \"Unknown error\",\n        tone: \"error\",\n      });\n    },\n  });\n\n  const uploadAttachment = useMutation({\n    mutationFn: async (file: File) => {\n      if (conversation) {\n        return issuesApi.uploadAttachment(conversation.agent.companyId, await resolveWritableIssueId(), file);\n      }\n      if (!loadedIssue)\n        throw new Error(\"Task details are still loading. Please try again.\");\n      return issuesApi.uploadAttachment(\n        loadedIssue.companyId,\n        loadedIssue.id,\n        file,\n      );\n    },\n    onSuccess: (result) => {\n      setAttachmentError(null);\n      queryClient.invalidateQueries({\n        queryKey: queryKeys.issues.attachments(issueId ?? result.issueId),\n      });\n      invalidateIssueDetail();\n      if (!issueId) void queryClient.invalidateQueries({ queryKey: queryKeys.issues.detail(result.issueId) });\n    },\n    onError: (err) => {\n      setAttachmentError(err instanceof Error ? err.message : \"Upload failed\");\n    },\n  });","sourceCodeStart":5188,"sourceCodeEnd":5224,"githubUrl":"https://github.com/paperclipai/paperclip/blob/3f1d897a7c018d76563a21c6e39c3c9b03933622/ui/src/pages/IssueDetail.tsx#L5188-L5224","documentation":"IssueDetail's attachment upload mutation requires either a conversation (which carries the issue's company) or a fully loaded `loadedIssue`. If neither is present when the user attempts to upload, the mutation throws 'Task details are still loading. Please try again.' This is a deliberate guard preventing an upload against an unresolved/undefined issue id.","triggerScenarios":"Selecting a file in the upload control before the issue detail query resolves (`loadedIssue` is null and there is no `conversation`); calling `uploadAttachment.mutate(file)` programmatically during initial page load; refetch invalidations that clear loadedIssue briefly.","commonSituations":"User drags a file onto the page immediately after opening a task; slow network makes the issue query take seconds; developer wires an upload handler in an effect that runs before react-query finishes fetching.","solutions":["Disable the attachment upload control until the issue query has loaded (e.g. `isSuccess` from useQuery).","Guard in the handler: check `loadedIssue || conversation` before opening the file picker or calling mutate.","Retry the upload after load completes rather than throwing — surface a toast instructing the user to retry once details are visible.","Verify resolveWritableIssueId/company resolution so the conversation path is used when available."],"exampleFix":"// before\nconst uploadAttachment = useMutation({\n  mutationFn: async (file: File) => {\n    if (!loadedIssue) throw new Error(\"Task details are still loading. Please try again.\");\n    ...\n  },\n});\n\n// after\n<input type=\"file\" disabled={!conversation && !loadedIssue} onChange={...} />","handlingStrategy":"validation","validationCode":"const canUpload = Boolean(conversation || loadedIssue);\nif (!canUpload) showToast(\"Task details are still loading. Please try again.\");","typeGuard":"const issueReady = (i: Issue | null | undefined): i is Issue => Boolean(i?.id && i?.companyId);","tryCatchPattern":"try {\n  await uploadAttachment.mutateAsync(file);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"still loading\")) {\n    showToast(\"Try again once the task details finish loading.\");\n  } else { throw err; }\n}","preventionTips":["Disable the upload input until the issue query succeeds","Defer programmatic uploads until loadedIssue or conversation exists","Show a loading skeleton instead of interactive controls during fetch","Prefer the conversation path which carries company context automatically"],"tags":["react-query","loading-state","upload","ui"],"backgroundTag":"invalid-state-transition","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"}