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
- Re-fetch the RPC URL via the core_rpc_url Tauri command rather than caching; the embedded core binds a fresh port per launch
- curl the resolved URL with an openhuman.ping POST and confirm a result field comes back
- Kill whatever else listens on that port (lsof -i :<port>) or let the core pick its own
- 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
- Derive the rpcUrl only from core_rpc_url, never persist the port
- Add a boot-time ping assertion after core start (run_server_embedded_with_ready) before first real call
- Keep dev-proxy rules away from the core's loopback port
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
- Core RPC returned an error
- [transport:lan] response missing result
- [transport:local] HTTP
- [transport:local] timed out after ms
- Cloud RPC returned an error
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)