{"record":{"id":"7c9aab3db67b4225","repo":"tinyhumansai/openhuman","slug":"not-running-in-tauri-7c9aab","errorCode":null,"errorMessage":"Not running in Tauri","messagePattern":"Not running in Tauri","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/utils/tauriCommands/heartbeat.ts","lineNumber":38,"sourceCode":"  subconscious_mode: SubconsciousMode;\n  triggers_enabled: boolean;\n  max_promotions_per_hour: number;\n}\n\nexport type HeartbeatSettingsPatch = Partial<HeartbeatSettings>;\n\nexport interface HeartbeatPlannerSummary {\n  source_events: number;\n  deliveries_attempted: number;\n  deliveries_sent: number;\n  deliveries_skipped_dedup: number;\n}\n\nexport async function openhumanHeartbeatSettingsGet(): Promise<\n  CommandResponse<{ settings: HeartbeatSettings }>\n> {\n  if (!isTauri()) {\n    throw new Error('Not running in Tauri');\n  }\n  return await callCoreRpc<CommandResponse<{ settings: HeartbeatSettings }>>({\n    method: 'openhuman.heartbeat_settings_get',\n  });\n}\n\nexport async function openhumanHeartbeatSettingsSet(\n  patch: HeartbeatSettingsPatch\n): Promise<CommandResponse<{ settings: HeartbeatSettings }>> {\n  if (!isTauri()) {\n    throw new Error('Not running in Tauri');\n  }\n  return await callCoreRpc<CommandResponse<{ settings: HeartbeatSettings }>>({\n    method: 'openhuman.heartbeat_settings_set',\n    params: patch,\n  });\n}\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/utils/tauriCommands/heartbeat.ts#L20-L56","documentation":"Fail-fast guard in the Tauri command wrapper for heartbeat settings RPC. callCoreRpc relays through Tauri's relay_http_rpc IPC command, which only exists inside the desktop shell; outside it (plain browser, Vite dev server, jsdom tests) the bridge is absent, so the wrapper throws 'Not running in Tauri' instead of an opaque invoke failure.","triggerScenarios":"Calling openhumanHeartbeatSettingsGet() or openhumanHeartbeatSettingsSet() while isTauri() is false: UI served by `pnpm dev` (Vite only, no Tauri host), a component test in jsdom, or any browser-only render of a settings component that calls the wrapper unconditionally.","commonSituations":"Developer runs `pnpm dev` instead of `pnpm dev:app`; Vitest renders a heartbeat settings panel without mocking app/src/utils/tauriCommands/heartbeat.","solutions":["Run the app inside the Tauri shell (`pnpm dev:app`) when exercising heartbeat settings","Gate the call site with isTauri() and hide or disable the heartbeat UI outside the shell","Mock the tauriCommands module (vi.mock) in Vitest for components that call it"],"exampleFix":"// before\nconst res = await openhumanHeartbeatSettingsGet();\n\n// after\nif (!isTauri()) {\n  setHeartbeatUnavailable(true);\n  return;\n}\nconst res = await openhumanHeartbeatSettingsGet();","handlingStrategy":"type-guard","validationCode":"import { isTauri } from '../../utils/tauri';\n\nif (!isTauri()) {\n  // render disabled/hidden state; do not call the wrapper\n}","typeGuard":"const canCallHeartbeatRpc = (): boolean => isTauri();","tryCatchPattern":"try {\n  const res = await openhumanHeartbeatSettingsGet();\n} catch (e) {\n  if (e instanceof Error && e.message === 'Not running in Tauri') {\n    // degrade gracefully: hide heartbeat UI, log once\n    return;\n  }\n  throw e;\n}","preventionTips":["Always branch on isTauri() before any callCoreRpc wrapper","Mock tauriCommands modules in Vitest instead of letting them hit the guard","Use `pnpm dev:app` (not `pnpm dev`) when a feature needs core RPC"],"tags":["tauri","environment","rpc","desktop"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}