tinyhumansai/openhuman · error · Error

Not running in Tauri

Error message

Not running in Tauri

What it means

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.

Source

Thrown at app/src/utils/tauriCommands/heartbeat.ts:38

  subconscious_mode: SubconsciousMode;
  triggers_enabled: boolean;
  max_promotions_per_hour: number;
}

export type HeartbeatSettingsPatch = Partial<HeartbeatSettings>;

export interface HeartbeatPlannerSummary {
  source_events: number;
  deliveries_attempted: number;
  deliveries_sent: number;
  deliveries_skipped_dedup: number;
}

export async function openhumanHeartbeatSettingsGet(): Promise<
  CommandResponse<{ settings: HeartbeatSettings }>
> {
  if (!isTauri()) {
    throw new Error('Not running in Tauri');
  }
  return await callCoreRpc<CommandResponse<{ settings: HeartbeatSettings }>>({
    method: 'openhuman.heartbeat_settings_get',
  });
}

export async function openhumanHeartbeatSettingsSet(
  patch: HeartbeatSettingsPatch
): Promise<CommandResponse<{ settings: HeartbeatSettings }>> {
  if (!isTauri()) {
    throw new Error('Not running in Tauri');
  }
  return await callCoreRpc<CommandResponse<{ settings: HeartbeatSettings }>>({
    method: 'openhuman.heartbeat_settings_set',
    params: patch,
  });
}

View on GitHub (pinned to a221052e0d)

Solutions

  1. Run the app inside the Tauri shell (`pnpm dev:app`) when exercising heartbeat settings
  2. Gate the call site with isTauri() and hide or disable the heartbeat UI outside the shell
  3. Mock the tauriCommands module (vi.mock) in Vitest for components that call it

Example fix

// before
const res = await openhumanHeartbeatSettingsGet();

// after
if (!isTauri()) {
  setHeartbeatUnavailable(true);
  return;
}
const res = await openhumanHeartbeatSettingsGet();
Defensive patterns

Strategy: type-guard

Validate before calling

import { isTauri } from '../../utils/tauri';

if (!isTauri()) {
  // render disabled/hidden state; do not call the wrapper
}

Type guard

const canCallHeartbeatRpc = (): boolean => isTauri();

Try / catch

try {
  const res = await openhumanHeartbeatSettingsGet();
} catch (e) {
  if (e instanceof Error && e.message === 'Not running in Tauri') {
    // degrade gracefully: hide heartbeat UI, log once
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: Developer runs `pnpm dev` instead of `pnpm dev:app`; Vitest renders a heartbeat settings panel without mocking app/src/utils/tauriCommands/heartbeat.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/7c9aab3db67b4225. Report an issue: GitHub.