moeru-ai/airi · error · Error

Chat session was removed before send completed

Error message

Chat session was removed before send completed

What it means

After runtime.ingest completes a turn, executeSend re-reads the session via getSessionMessagesIfLoaded; when the session is no longer loaded in memory it returns undefined and this error is thrown. It specifically detects that the session was deleted or cleared while the generation was in flight, so the produced reply has nowhere to be attached and the result is discarded.

Source

Thrown at packages/stage-ui/src/stores/chat.ts:420

    await runtime.ingest(payload.text, {
      model: modelId,
      chatProvider,
      attachments: payload.attachments,
      input: payload.input,
      toolReferences: payload.tools,
      temperature: payload.temperature ?? consciousnessStore.activeTemperature,
      topP: payload.topP ?? consciousnessStore.activeTopP,
      // Resolve this function after the request reaches the per-session queue.
      // The history then contains tool names from every earlier queued turn.
      tools: async () => {
        const references = collectToolReferences(payload.sessionId, payload.tools)
        return llmToolsStore.getToolsByNames(...references.map(tool => tool.name))
      },
    }, payload.sessionId)

    const completedMessages = chatSession.getSessionMessagesIfLoaded(payload.sessionId)
    if (!completedMessages)
      throw new Error('Chat session was removed before send completed')

    return {
      messages: completedMessages
        .slice(messageCount)
        .map(message => structuredClone(toRaw(message))),
      sessionId: payload.sessionId,
    }
  }

  /** Sends one serializable chat request through the elected leader. */
  async function send(payload: ChatSendPayload): Promise<ChatSendResult> {
    try {
      return await executeSend(payload)
    }
    catch (error) {
      appendSendError(payload.sessionId, error)
      throw error
    }

View on GitHub (pinned to f679616c34)

Solutions

  1. Treat this specific error as a cancellation in the UI (dismiss quietly) rather than showing a hard failure.
  2. Block or warn on session deletion while a send for that session is in flight, or abort the in-flight send on deletion.
  3. Refresh the session list so the removed session disappears from the UI.
  4. If the session is expected to exist, recreate it and resend.

Example fix

// before
try {
  await chatStore.send({ sessionId, text })
}
catch (error) {
  toast.error(String(error))
}

// after
try {
  await chatStore.send({ sessionId, text })
}
catch (error) {
  if (errorMessageFrom(error) === 'Chat session was removed before send completed') {
    // generation finished but the user deleted the session; nothing to show
    return
  }
  toast.error(errorMessageFrom(error) ?? 'Send failed')
}
Defensive patterns

Strategy: try-catch

Try / catch

const SESSION_REMOVED = 'Chat session was removed before send completed'
try {
  await chatStore.send({ sessionId, text })
}
catch (error) {
  if (errorMessageFrom(error) === SESSION_REMOVED) {
    // the reply completed but the session is gone: silent cancel
    return
  }
  toast.error(errorMessageFrom(error) ?? 'Send failed')
}

Prevention

When it happens

Trigger: Deleting the session (or clearing it) while an assistant reply is streaming; switching character views that unload sessions mid-generation; another tab/window removing the session during the request; programmatic clearSession racing a queued send.

Common situations: Impatient users deleting a session while a slow model responds; multi-tab usage; long tool-calling turns during which the user navigates away and clears state.

Related errors


AI-assisted analysis of moeru-ai/airi@f679616c34 (2026-08-18). Data as JSON: /api/errors/2770c5d3d09fda44. Report an issue: GitHub.