{"record":{"id":"a87fa4fca2865b53","repo":"iOfficeAI/AionUi","slug":"fork-returned-no-conversation","errorCode":null,"errorMessage":"fork returned no conversation","messagePattern":"fork returned no conversation","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/desktop/src/renderer/hooks/chat/useForkConversation.ts","lineNumber":50,"sourceCode":" * forked conversation, and pre-warm its runtime so a backend-side fork failure\n * surfaces immediately instead of on the first send.\n */\nexport function useForkConversation(conversationId: string | undefined) {\n  const { t } = useTranslation();\n  const navigate = useNavigate();\n  const forkingRef = useRef(false);\n\n  return useCallback(\n    async (messageId: string) => {\n      if (!conversationId || forkingRef.current) return;\n      forkingRef.current = true;\n      try {\n        const forked = await ipcBridge.conversation.fork.invoke({\n          conversation_id: conversationId,\n          message_id: messageId,\n        });\n        if (!forked?.id) {\n          throw new Error('fork returned no conversation');\n        }\n        emitter.emit('chat.history.refresh');\n        void navigate(`/conversation/${forked.id}`);\n        // Lazy fork + eager surfacing: materialize the backend session now so\n        // \"parent session gone\" style failures show up before the first send.\n        void ipcBridge.conversation.ensureRuntime.invoke({ conversation_id: forked.id }).catch((): void => undefined);\n      } catch (error) {\n        console.error('Failed to fork conversation:', error);\n        Message.error(getForkErrorMessage(error, t));\n      } finally {\n        forkingRef.current = false;\n      }\n    },\n    [conversationId, navigate, t]\n  );\n}\n","sourceCodeStart":32,"sourceCodeEnd":67,"githubUrl":"https://github.com/iOfficeAI/AionUi/blob/711aa0550ee183ea495dc33e2c05c7943b70a60a/packages/desktop/src/renderer/hooks/chat/useForkConversation.ts#L32-L67","documentation":"This error is thrown when the IPC call that forks a conversation returns a falsy result or an object without an `id`. It is a defensive guard in the renderer after invoking `ipcBridge.conversation.fork.invoke`, meaning the main process either failed silently or returned an unexpected payload shape.","triggerScenarios":"Calling the fork-conversation flow (fork a chat from a given message) when the backend fork IPC handler resolves with `undefined`, `null`, or a conversation object lacking `id` — e.g. the source conversation/message no longer exists in storage or the IPC channel errored without rejecting.","commonSituations":"The original conversation was deleted between opening the UI and clicking fork; corrupted or missing conversation storage on disk; a main-process fork handler that swallows errors and returns undefined; mid-development changes to the fork IPC contract.","solutions":["Verify the source conversation_id and message_id still exist before forking (re-fetch history)","Check the main-process implementation of the conversation.fork IPC handler to confirm it always returns the forked conversation or rejects on failure","Inspect main-process logs for storage/DB errors during fork","Add a regression test asserting the fork handler rejects instead of resolving with an empty payload"],"exampleFix":"// before\nconst forked = await ipcBridge.conversation.fork.invoke({ conversation_id: conversationId, message_id: messageId });\nif (!forked?.id) {\n  throw new Error('fork returned no conversation');\n}\n\n// after (surface actionable detail)\nif (!forked?.id) {\n  throw new Error(`fork returned no conversation (source=${conversationId}, message=${messageId ?? 'latest'})`);\n}","handlingStrategy":"validation","validationCode":"const exists = await ipcBridge.conversation.get.invoke({ conversation_id: conversationId });\nif (!exists) { /* refresh history, abort fork */ }","typeGuard":"const isForkedConversation = (v: unknown): v is { id: string } =>\n  typeof v === 'object' && v !== null && typeof (v as { id?: unknown }).id === 'string';","tryCatchPattern":"catch (e) { toast.error(t('chat.forkFailed')); await refreshConversationList(); }","preventionTips":["Disable the fork action while conversation history is still loading","Re-validate conversation existence before fork if the tab was idle for a long time"],"tags":["ipc","conversation","fork","renderer","defensive-guard"],"backgroundTag":"ipc-handler-returned-invalid-payload","analyzedSha":"711aa0550ee183ea495dc33e2c05c7943b70a60a","analyzedAt":"2026-08-28T07:56:06.558Z","schemaVersion":2},"datasetVersion":"2026-08-28T11:17:15.048Z"}