{"record":{"id":"cd6ddf9ffe2f2d12","repo":"different-ai/openwork","slug":"app-error-not-connected","errorCode":null,"errorMessage":"app.error_not_connected","messagePattern":"app\\.error_not_connected","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/app/src/react-app/domains/session/sync/actions-store.ts","lineNumber":642,"sourceCode":"      reason: \"session action requested abort\",\n    });\n  }\n\n  function retryLastPrompt() {\n    const text = lastPromptSent().trim();\n    if (!text) return;\n    void sendPrompt({\n      mode: \"prompt\",\n      text,\n      parts: [{ type: \"text\", text }],\n      attachments: [],\n    });\n  }\n\n  async function compactCurrentSession(sessionIdOverride?: string) {\n    const c = options.client();\n    if (!c) {\n      throw new Error(t(\"app.error_not_connected\"));\n    }\n\n    const sessionID = (sessionIdOverride ?? options.selectedSessionId() ?? \"\").trim();\n    if (!sessionID) {\n      throw new Error(t(\"app.error_compact_no_session_id\"));\n    }\n\n    const visible = options.messages();\n    if (!visible.length) {\n      throw new Error(t(\"app.error_compact_empty\"));\n    }\n\n    const model = options.selectedSessionModel();\n    const startedAt = perfNow();\n    const modelLabel = `${model.providerID}/${model.modelID}`;\n    recordPerfLog(options.developerMode(), \"session.compact\", \"start\", {\n      sessionID,\n      messageCount: visible.length,","sourceCodeStart":624,"sourceCodeEnd":660,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/app/src/react-app/domains/session/sync/actions-store.ts#L624-L660","documentation":"compactCurrentSession requires an active client transport; if options.client() returns null/undefined — meaning the UI has no connected server session — it throws the localized 'app.error_not_connected' before doing anything. This prevents compact requests from being issued into a dead/absent connection.","triggerScenarios":"User triggers 'compact session' (from UI or with a sessionIdOverride) while the app is disconnected: server not started, connection dropped, or the action invoked before the client finished connecting.","commonSituations":"Server crashed or exited while a conversation stayed open; user ran compact during startup before the connection was ready; network outage dropped the websocket.","solutions":["Reconnect to the server (restart or reconnect the session) and retry the compact action.","Disable/gate the compact action in the UI until the client connection is ready.","Check server logs for why the transport dropped if disconnection was unexpected."],"exampleFix":"// before\nasync function compactCurrentSession(id?: string) {\n  const c = options.client();\n  if (!c) throw new Error(t(\"app.error_not_connected\"));\n// after (caller gate)\nif (!isConnected()) {\n  showToast(\"Reconnect before compacting\");\n  return;\n}\nawait compactCurrentSession();","handlingStrategy":"validation","validationCode":"const c = options.client();\nif (!c) {\n  showToast(\"Reconnect to the server first\");\n  return;\n}\nawait compactCurrentSession();","typeGuard":"function isConnectedClient(c: unknown): boolean {\n  return typeof c === \"object\" && c !== null;\n}","tryCatchPattern":"try {\n  await compactCurrentSession();\n} catch (e) {\n  if (e instanceof Error && e.message === \"app.error_not_connected\") {\n    await reconnectClient();\n    showToast(\"Was disconnected — reconnected, retry compact\");\n    return;\n  }\n  throw e;\n}","preventionTips":["Gate connection-dependent actions (compact, send, etc.) on client readiness in the UI.","Auto-reconnect on transport loss so the client is rarely null during user actions.","Watch server health so unexpected disconnects are surfaced before the user triggers actions."],"tags":["connection","compact","session"],"backgroundTag":"not-connected","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}