{"record":{"id":"2770c5d3d09fda44","repo":"moeru-ai/airi","slug":"chat-session-was-removed-before-send-completed","errorCode":null,"errorMessage":"Chat session was removed before send completed","messagePattern":"Chat session was removed before send completed","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/stage-ui/src/stores/chat.ts","lineNumber":420,"sourceCode":"    await runtime.ingest(payload.text, {\n      model: modelId,\n      chatProvider,\n      attachments: payload.attachments,\n      input: payload.input,\n      toolReferences: payload.tools,\n      temperature: payload.temperature ?? consciousnessStore.activeTemperature,\n      topP: payload.topP ?? consciousnessStore.activeTopP,\n      // Resolve this function after the request reaches the per-session queue.\n      // The history then contains tool names from every earlier queued turn.\n      tools: async () => {\n        const references = collectToolReferences(payload.sessionId, payload.tools)\n        return llmToolsStore.getToolsByNames(...references.map(tool => tool.name))\n      },\n    }, payload.sessionId)\n\n    const completedMessages = chatSession.getSessionMessagesIfLoaded(payload.sessionId)\n    if (!completedMessages)\n      throw new Error('Chat session was removed before send completed')\n\n    return {\n      messages: completedMessages\n        .slice(messageCount)\n        .map(message => structuredClone(toRaw(message))),\n      sessionId: payload.sessionId,\n    }\n  }\n\n  /** Sends one serializable chat request through the elected leader. */\n  async function send(payload: ChatSendPayload): Promise<ChatSendResult> {\n    try {\n      return await executeSend(payload)\n    }\n    catch (error) {\n      appendSendError(payload.sessionId, error)\n      throw error\n    }","sourceCodeStart":402,"sourceCodeEnd":438,"githubUrl":"https://github.com/moeru-ai/airi/blob/f679616c34f1cf6d282c8d64264242af944b3fed/packages/stage-ui/src/stores/chat.ts#L402-L438","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Treat this specific error as a cancellation in the UI (dismiss quietly) rather than showing a hard failure.","Block or warn on session deletion while a send for that session is in flight, or abort the in-flight send on deletion.","Refresh the session list so the removed session disappears from the UI.","If the session is expected to exist, recreate it and resend."],"exampleFix":"// before\ntry {\n  await chatStore.send({ sessionId, text })\n}\ncatch (error) {\n  toast.error(String(error))\n}\n\n// after\ntry {\n  await chatStore.send({ sessionId, text })\n}\ncatch (error) {\n  if (errorMessageFrom(error) === 'Chat session was removed before send completed') {\n    // generation finished but the user deleted the session; nothing to show\n    return\n  }\n  toast.error(errorMessageFrom(error) ?? 'Send failed')\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"const SESSION_REMOVED = 'Chat session was removed before send completed'\ntry {\n  await chatStore.send({ sessionId, text })\n}\ncatch (error) {\n  if (errorMessageFrom(error) === SESSION_REMOVED) {\n    // the reply completed but the session is gone: silent cancel\n    return\n  }\n  toast.error(errorMessageFrom(error) ?? 'Send failed')\n}","preventionTips":["Block or confirm session deletion while a send for that session is in flight.","Abort in-flight sends when clearing/deleting a session, so results are not orphaned.","Treat this exact message as cancellation, not failure, in UI error reporting.","After multi-tab deletions, refresh the session list so removed sessions vanish from the UI."],"tags":["chat","race-condition","session","lifecycle"],"backgroundTag":"stale-session-race","analyzedSha":"f679616c34f1cf6d282c8d64264242af944b3fed","analyzedAt":"2026-08-18T17:29:58.153Z","contentChangedAt":"2026-08-18T17:29:58.153Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}