tinyhumansai/openhuman · error

[transport:local] response missing result

Error message

[transport:local] response missing result

What it means

Identical contract to the LAN variant: LocalTransport requires every 2xx response body to own either `error` or `result`. This fires when http://127.0.0.1:<port>/rpc answers 200 with JSON that has neither — the URL resolved to something that is not the JSON-RPC endpoint, or the response was rewritten in flight.

Solutions

  1. Re-fetch the RPC URL via the core_rpc_url Tauri command rather than caching; the embedded core binds a fresh port per launch
  2. curl the resolved URL with an openhuman.ping POST and confirm a result field comes back
  3. Kill whatever else listens on that port (lsof -i :<port>) or let the core pick its own
  4. Disable any dev proxy rule that intercepts the core port
Defensive patterns

Strategy: type-guard

Validate before calling

// Reject non-RPC URLs when wiring the transport:
function assertRpcUrl(url: string): void {
  if (!/^https?:\/\/127\.0\.0\.1:\d+\/rpc$/.test(url)) {
    throw new Error(`suspicious local rpcUrl: ${url}`);
  }
}

Type guard

function hasResultField(body: unknown): boolean {
  return typeof body === 'object' && body !== null && Object.prototype.hasOwnProperty.call(body, 'result');
}

Try / catch

try { await local.call('openhuman.ping', {}); }
catch (err) {
  if (err instanceof Error && err.message.includes('response missing result')) {
    // re-resolve rpcUrl via core_rpc_url — the port likely rotated or the URL points at /health
  } else throw err;
}

Prevention

When it happens

Trigger: getCoreRpcUrl() returning the /health endpoint, a stale port now owned by another local service (Vite dev server, another app), a dev proxy (Vite server.proxy) mangling the body, or an old core whose envelope predates strict checks.

Common situations: Port collision after core restart picked a new port while the client cached the old one; OPENHUMAN_CORE_REUSE_EXISTING=1 pointing at a manually started core on a nonstandard route; local HTTP debugging proxies (mitmproxy) re-encoding responses.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17). Data as JSON: /api/errors/cc39a7bd97153e65. Report an issue: GitHub.

Appendix: source

Thrown at app/src/services/transport/LocalTransport.ts:87

      }
      throw err;
    } finally {
      clearTimeout(timeoutId);
    }

    if (!response.ok) {
      const text = await response.text();
      throw new Error(`[transport:local] HTTP ${response.status}: ${text || response.statusText}`);
    }

    const json = (await response.json()) as JsonRpcResponse<T>;

    if (json.error) {
      logErr('[transport:local] ← %s error: %s', method, json.error.message);
      throw new Error(json.error.message ?? 'Core RPC returned an error');
    }
    if (!Object.prototype.hasOwnProperty.call(json, 'result')) {
      throw new Error('[transport:local] response missing result');
    }

    log('[transport:local] ← %s id=%d ok', method, id);
    return json.result as T;
  }

  async *stream<T>(
    method: string,
    params: unknown,
    opts?: { signal?: AbortSignal }
  ): AsyncIterable<T> {
    // Local HTTP doesn't support streaming natively in this project.
    // Fall back to a single call and yield the result.
    const result = await this.call<T>(method, params, opts);
    yield result;
  }

  async isHealthy(): Promise<boolean> {

View on GitHub (pinned to 7491200858)