iOfficeAI/AionUi · error

fork returned no conversation

Error message

fork returned no conversation

What it means

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.

Source

Thrown at packages/desktop/src/renderer/hooks/chat/useForkConversation.ts:50

 * forked conversation, and pre-warm its runtime so a backend-side fork failure
 * surfaces immediately instead of on the first send.
 */
export function useForkConversation(conversationId: string | undefined) {
  const { t } = useTranslation();
  const navigate = useNavigate();
  const forkingRef = useRef(false);

  return useCallback(
    async (messageId: string) => {
      if (!conversationId || forkingRef.current) return;
      forkingRef.current = true;
      try {
        const forked = await ipcBridge.conversation.fork.invoke({
          conversation_id: conversationId,
          message_id: messageId,
        });
        if (!forked?.id) {
          throw new Error('fork returned no conversation');
        }
        emitter.emit('chat.history.refresh');
        void navigate(`/conversation/${forked.id}`);
        // Lazy fork + eager surfacing: materialize the backend session now so
        // "parent session gone" style failures show up before the first send.
        void ipcBridge.conversation.ensureRuntime.invoke({ conversation_id: forked.id }).catch((): void => undefined);
      } catch (error) {
        console.error('Failed to fork conversation:', error);
        Message.error(getForkErrorMessage(error, t));
      } finally {
        forkingRef.current = false;
      }
    },
    [conversationId, navigate, t]
  );
}

View on GitHub (pinned to 711aa0550e)

Solutions

  1. Verify the source conversation_id and message_id still exist before forking (re-fetch history)
  2. Check the main-process implementation of the conversation.fork IPC handler to confirm it always returns the forked conversation or rejects on failure
  3. Inspect main-process logs for storage/DB errors during fork
  4. Add a regression test asserting the fork handler rejects instead of resolving with an empty payload

Example fix

// before
const forked = await ipcBridge.conversation.fork.invoke({ conversation_id: conversationId, message_id: messageId });
if (!forked?.id) {
  throw new Error('fork returned no conversation');
}

// after (surface actionable detail)
if (!forked?.id) {
  throw new Error(`fork returned no conversation (source=${conversationId}, message=${messageId ?? 'latest'})`);
}
Defensive patterns

Strategy: validation

Validate before calling

const exists = await ipcBridge.conversation.get.invoke({ conversation_id: conversationId });
if (!exists) { /* refresh history, abort fork */ }

Type guard

const isForkedConversation = (v: unknown): v is { id: string } =>
  typeof v === 'object' && v !== null && typeof (v as { id?: unknown }).id === 'string';

Try / catch

catch (e) { toast.error(t('chat.forkFailed')); await refreshConversationList(); }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of iOfficeAI/AionUi@711aa0550e (2026-08-28). Data as JSON: /api/errors/a87fa4fca2865b53. Report an issue: GitHub.