tinyhumansai/openhuman · error

Core RPC token unavailable in Tauri; local RPC auth cannot b

Error message

Core RPC token unavailable in Tauri; local RPC auth cannot be satisfied

What it means

Thrown by callCoreRpc when running inside Tauri and the bearer token could not be obtained: the shell mints a per-launch hex token for the embedded core (handed over via run_server_embedded_with_ready), and every local RPC must present it. When both the cloud-stored token and the Tauri core_rpc_token command yield nothing, the request cannot be authenticated and is refused before hitting the wire.

Source

Thrown at app/src/services/coreRpcClient.ts:679

  const effectiveTimeoutMs = resolvePerCallTimeoutMs(timeoutMs);
  const payload: JsonRpcRequestBody = {
    jsonrpc: '2.0',
    id: nextJsonRpcId++,
    method: normalizedMethod,
    params: params ?? {},
  };

  try {
    const [rpcUrl, token] = await Promise.all([getCoreRpcUrl(), getCoreRpcToken()]);
    coreRpcLog('HTTP request', { id: payload.id, method: payload.method });
    if (normalizedMethod === 'openhuman.auth_store_session') {
      coreRpcLog('[rpc] auth_store_session routing', {
        rpcUrl,
        tokenSource: getStoredCoreToken() ? 'cloud-stored' : 'local-resolved',
      });
    }
    if (isTauri() && !token) {
      throw new Error('Core RPC token unavailable in Tauri; local RPC auth cannot be satisfied');
    }

    const headers: Record<string, string> = { 'Content-Type': 'application/json' };
    if (token) {
      headers['Authorization'] = `Bearer ${token}`;
    }
    // Bound the fetch. Without this a hung core sidecar would block every
    // caller (and the UI) forever. We use a manual AbortController +
    // setTimeout rather than AbortSignal.timeout() so test fake timers can
    // drive the abort deterministically. Per-call `timeoutMs` (clamped) lets
    // legitimately-slow RPCs such as first-launch `app_state_snapshot`
    // (#2156) opt into a longer-but-still-bounded budget.
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), effectiveTimeoutMs);
    let response: Response;
    try {
      if (isTauri() && rpcUrlNeedsShellRelay(rpcUrl)) {
        // Self-hosted runtime on a LAN IP — the secure `tauri://localhost`

View on GitHub (pinned to a221052e0d)

Solutions

  1. Await the app's boot gates (CoreStateProvider / BootCheckGate) before issuing RPCs from new code — they exist precisely to sequence this
  2. Restart the app; a fresh launch re-mints the token via start_core_process
  3. Check the core actually booted: core logs / the health endpoint on the core port
  4. Retry the call after a short delay — token availability is transient during boot
  5. If developing with an external core, set OPENHUMAN_CORE_TOKEN or use the documented reuse env var

Example fix

// before
const snap = await callCoreRpc({ method: 'openhuman.app_state_snapshot' });

// after
await coreReady; // gate from CoreStateProvider / boot promise
const snap = await callCoreRpc({ method: 'openhuman.app_state_snapshot' });
Defensive patterns

Strategy: retry

Validate before calling

// Wait for boot before the first RPC instead of racing the token
await coreStateReady; // exposed by CoreStateProvider / BootCheckGate
await callCoreRpc({ method: 'openhuman.app_state_snapshot' });

Try / catch

for (let attempt = 0; attempt < 5; attempt++) {
  try {
    return await callCoreRpc(payload);
  } catch (e) {
    if (e instanceof Error && e.message.includes('token unavailable')) {
      await delay(500 * 2 ** attempt); // core still booting — token arrives shortly
      continue;
    }
    throw e;
  }
}

Prevention

When it happens

Trigger: An RPC fires before the core process is ready (the shell has not yet minted/exposed the token — e.g. a service or effect racing app boot), the core crashed at startup so the token command fails/returns nothing, or the Tauri IPC layer (CEF window.ipc.postMessage path) fails synchronously.

Common situations: First-launch races (early fetches like app_state_snapshot firing before BootCheckGate/CoreStateProvider complete); core crash-loop on boot (bad config, corrupted workspace); running the UI against a core that exited; CEF IPC quirks referenced by the Sentry TAURI-REACT issues in the source comment.

Related errors


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