{"record":{"id":"e49c316f5252f17f","repo":"chatboxai/chatbox","slug":"session-not-found","errorCode":null,"errorMessage":"Session not found","messagePattern":"Session not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"src/renderer/components/InputBox/useReasoningControlState.ts","lineNumber":164,"sourceCode":"  // Existing sessions persist level changes directly (see handleReasoningLevelChange);\n  // the patch is only needed when the session does not exist yet and will be created on\n  // submit. It carries every per-model draft; 'default' drafts need no entry since a\n  // new session starts at the default level anyway.\n  const settingsPatch = useMemo<Partial<SessionSettings> | undefined>(() => {\n    if (!isNewSession) return undefined\n    const byModel: Record<string, ProviderOptions> = {}\n    for (const [key, entry] of Object.entries(draftByModel)) {\n      if (entry.options) byModel[key] = entry.options\n    }\n    if (Object.keys(byModel).length === 0) return undefined\n    return { providerOptionsByModel: byModel }\n  }, [isNewSession, draftByModel])\n\n  const persistProviderOptions = useCallback(\n    async (sessionId: string, nextProviderOptions?: ProviderOptions) => {\n      await chatStore.updateSession(sessionId, (session) => {\n        if (!session) {\n          throw new Error('Session not found')\n        }\n        return {\n          ...session,\n          settings: {\n            ...session.settings,\n            ...setReasoningProviderOptionsForModel(\n              session.settings,\n              model?.provider,\n              model?.modelId,\n              nextProviderOptions\n            ),\n          },\n        }\n      })\n    },\n    [model?.provider, model?.modelId]\n  )\n","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/chatboxai/chatbox/blob/81571269addb6bafb589a920b2883f1e1e084fd1/src/renderer/components/InputBox/useReasoningControlState.ts#L146-L182","documentation":"Thrown inside the updater callback passed to chatStore.updateSession when the session with the given sessionId is not present in the store. The callback is invoked to merge reasoning provider options into the session settings; a missing session means the id is stale — the session was deleted, not yet created, or the id is wrong. This is a logic/consistency error, not a network failure.","triggerScenarios":"persistProviderOptions(sessionId, options) is called with a sessionId that chatStore.updateSession's callback receives as undefined. Happens when the user navigates away or deletes the session between the reasoning-level change and the persist call, or when currentSessionId is read from a stale closure.","commonSituations":"User changes reasoning level then immediately deletes/switches the session; the component is unmounted mid-async; a race between session creation and the first options persist. The hook guards new sessions via draftByModel but existing sessions hit this path.","solutions":["Check that the session still exists (chatStore.getSession(sessionId)) before calling updateSession.","Make the updater callback return undefined or a no-op when session is null instead of throwing.","Abort the persist when the component unmounts (AbortController) to avoid a stale-session write."],"exampleFix":"// before\nawait chatStore.updateSession(sessionId, (session) => {\n  if (!session) throw new Error('Session not found')\n  return { ...session, settings: { ... } }\n})\n\n// after — tolerate a missing session (deleted between read and write)\nawait chatStore.updateSession(sessionId, (session) => {\n  if (!session) return session // no-op; session was removed\n  return { ...session, settings: { ... } }\n})","handlingStrategy":"validation","validationCode":"// Check the session exists before persisting options.\nfunction sessionExists(chatStore: any, sessionId: string): boolean {\n  return !!chatStore.getSession?.(sessionId)\n}\nif (sessionId && !sessionExists(chatStore, sessionId)) return","typeGuard":null,"tryCatchPattern":"// Prefer making the updater tolerate a missing session, but if throwing is kept:\ntry {\n  await persistProviderOptions(sessionId, options)\n} catch (e) {\n  if (e instanceof Error && /Session not found/i.test(e.message)) {\n    // session was deleted concurrently; swallow\n    return\n  }\n  throw e\n}","preventionTips":["Make the updateSession callback return the session unchanged when it is null instead of throwing.","Abort in-flight persists when the component unmounts or the active session changes.","Read sessionId from a ref, not a stale closure, to avoid writing to a swapped session."],"tags":["state-management","session","reasoning","react","race-condition"],"backgroundTag":null,"analyzedSha":"81571269addb6bafb589a920b2883f1e1e084fd1","analyzedAt":"2026-08-12T21:51:44.981Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}