tinyhumansai/openhuman · error
Core RPC response missing result
Error message
Core RPC response missing result
What it means
Thrown when a call to the local core returns HTTP 200 with valid JSON that contains neither an `error` field nor a `result` field. Per JSON-RPC 2.0, a response object must have exactly one of `result` or `error`, so this is a malformed/foreign response — the client deliberately refuses to treat `undefined` as a result. It fires after the `json.error` branch, so the server really did answer 'success-shaped' but with no payload.
Source
Thrown at app/src/services/coreRpcClient.ts:763
throw new CoreRpcError(httpMessage, kind, response.status);
}
const json = (await response.json()) as JsonRpcResponse<T>;
if (json.error) {
coreRpcError('HTTP error response', {
id: payload.id,
method: payload.method,
error: json.error,
});
const rawMessage = json.error.message || 'Core RPC returned an error';
const kind = classifyRpcError(rawMessage, undefined, json.error.data);
if (kind === 'auth_expired' && !suppressAuthExpiredEvent)
dispatchAuthExpired(payload.method, classifyAuthExpiredReason(rawMessage, undefined));
throw new CoreRpcError(rawMessage, kind, undefined, json.error.data);
}
if (!Object.prototype.hasOwnProperty.call(json, 'result')) {
throw new Error('Core RPC response missing result');
}
coreRpcLog('HTTP response', { id: payload.id, method: payload.method });
return json.result as T;
} catch (err) {
coreRpcError('Core RPC call failed', sanitizeError(err));
if (err instanceof CoreRpcError) throw err;
const message = coreRpcErrorMessage(err);
throw new CoreRpcError(message, classifyRpcError(message));
}
}
View on GitHub (pinned to a221052e0d)
Solutions
- Verify the resolved RPC URL — log `await getCoreRpcUrl()` and confirm it ends in `/rpc` on the core port from `core_rpc_url`
- curl the endpoint directly with a minimal JSON-RPC frame (`{"jsonrpc":"2.0","id":1,"method":"openhuman.ping","params":{}}`) and inspect the raw body
- If using a mock/stub server, make it reply with `{jsonrpc:'2.0', id, result:{}}` for every frame
- Check for a proxy or interceptor between renderer and core and bypass it for `/rpc`
Example fix
// before (stub server replying empty)
app.post('/rpc', (_req, res) => res.json({}));
// after
app.post('/rpc', (req, res) =>
res.json({ jsonrpc: '2.0', id: req.body.id, result: { pong: true } })
); Defensive patterns
Strategy: try-catch
Try / catch
try { const r = await callCoreRpc<T>(m, p); }
catch (e) {
if (e instanceof Error && e.message === 'Core RPC response missing result') {
logRpcShapeIssue(m); // endpoint config problem, not a business failure
return undefined;
}
throw e;
} Prevention
- Assert the RPC URL ends with /rpc on the core port before first use
- Smoke-test every environment once with openhuman.ping — shape errors surface immediately
- Make mock/stub servers reply with full JSON-RPC frames ({jsonrpc, id, result})
When it happens
Trigger: The RPC URL resolves to an endpoint that returns 200 + JSON without JSON-RPC shape: a health endpoint, a mock/stub server replying `{}`, or a proxy that rewrites the body. Also a core bug or middleware that emits `{jsonrpc, id}` with the result dropped during serialization.
Common situations: `rpcUrl` pointing at `/health` or the wrong port instead of `http://127.0.0.1:<port>/rpc`; running against a hand-rolled test stub that replies `{ok:true}`; an intermediate dev proxy (Vite middleware, service worker) stripping the body; version skew after the wire shape changed.
Related errors
- provider_surfaces_list_queue: unexpected empty response
- Core RPC returned an error
- Core rejected the meet_agent_list_calls request.
- Core rejected the meet_agent_get_call_detail request.
- Core rejected the meet_list_upcoming request.
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/186432a72def64be.
Report an issue: GitHub.