tinyhumansai/openhuman · error · Error
[transport:local] response missing result
Error message
[transport:local] response missing result
What it means
HTTP 200 from the local endpoint, but the parsed JSON has neither an `error` nor an own `result` property (checked via hasOwnProperty) — the body is not a JSON-RPC envelope at all. The transport refuses to guess and aborts.
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 a221052e0d)
Solutions
- Log the raw response text before parsing to see what actually came back
- Verify localRpcUrl is the exact /rpc path of the core's HTTP host
- Ensure the request body is a well-formed JSON-RPC request with an id (notifications legitimately get no result)
- Exclude /rpc from any proxy/middleware that rewrites response bodies
Example fix
// before
const json = (await response.json()) as JsonRpcResponse<T>;
// after — surface what the 200 actually contained
const text = await response.text();
let json: JsonRpcResponse<T>;
try {
json = JSON.parse(text);
} catch {
throw new Error(`[transport:local] non-JSON 200 body: ${text.slice(0, 200)}`);
} Defensive patterns
Strategy: try-catch
Type guard
function isJsonRpcEnvelope(v: unknown): v is { result?: unknown; error?: { code?: number; message?: string } } {
return typeof v === 'object' && v !== null && ('result' in v || 'error' in v);
} Try / catch
Catch, then immediately log which URL was called — this error almost always means wrong endpoint or a rewriting proxy, not a flaky core; fix the endpoint instead of retrying.
Prevention
- Point the transport only at the core's exact /rpc path
- When adding core HTTP middleware, guarantee it never returns 200 with a non-envelope JSON body
- Include the request id when logging so a notification-style reply is distinguishable
When it happens
Trigger: A 200 whose JSON is an empty object, a bare value, or middleware's own JSON (e.g. an auth layer returning {ok:false}); localRpcUrl pointing at the wrong endpoint such as /health instead of /rpc; a gateway rewriting the body.
Common situations: localRpcUrl misconfigured to a non-/rpc path; an external core behind a reverse proxy that rewrites or wraps response bodies; a mock server configured for a different method; a notification-style request (no id) getting an id-less reply.
Related errors
- Core RPC returned an error
- Core returned an empty backend URL
- Cloud RPC returned an error
- [transport:cloud] response missing result
- LAN RPC returned an error
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/cc39a7bd97153e65.
Report an issue: GitHub.