tinyhumansai/openhuman · error · CoreRpcError
Core RPC returned an error
Error message
Core RPC returned an error
What it means
Fallback message used when the embedded Rust core answers a JSON-RPC call with an `error` object whose `message` field is missing or empty (`json.error.message || 'Core RPC returned an error'`). The actual failure happened core-side in a controller handler; this string only stands in for an empty message. The thrown value is a `CoreRpcError` that also carries `kind` (from `classifyRpcError(rawMessage, undefined, json.error.data)`) and the raw `json.error.data`, which usually contain the real diagnosis even when the message is blank.
Source
Thrown at app/src/services/coreRpcClient.ts:760
payload.method,
classifyAuthExpiredReason(text || response.statusText, response.status)
);
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
- Inspect the caught `CoreRpcError`'s `kind` and `data` fields — the message can be empty while `data` holds a typed kind (e.g. `{ kind: 'ThreadNotFound' }`)
- Enable the debug logger (`DEBUG=core-rpc:error` or `debug.enable('core-rpc:error')`) and reproduce — the full `json.error` object is logged with id/method before the throw
- Check the core-side log file for the same timestamp; the Rust handler usually logs the underlying cause
- Rebuild/restart the core (`pnpm dev:app` or `restart_core_process`) so the controller set matches the frontend expectations
Example fix
// before
try { await coreRpcClient.call('openhuman.memory_search', params); }
catch (e) { toast(String(e)); }
// after
import { CoreRpcError } from '../services/coreRpcClient';
try { await coreRpcClient.call('openhuman.memory_search', params); }
catch (e) {
if (e instanceof CoreRpcError) {
// data carries the typed reason even when message is the empty fallback
toast(e.data ? JSON.stringify(e.data) : e.message, e.kind);
} else throw e;
} Defensive patterns
Strategy: try-catch
Type guard
import { CoreRpcError } from '../services/coreRpcClient';
function isCoreRpcError(e: unknown): e is CoreRpcError {
return e instanceof CoreRpcError;
} Try / catch
try {
const r = await coreRpcClient.call('openhuman.x_y', params);
} catch (e) {
if (e instanceof CoreRpcError) {
// message may be the empty fallback — prefer data/kind
report({ kind: e.kind, data: e.data, message: e.message });
if (e.kind === 'auth_expired') reAuth();
return;
}
throw e;
} Prevention
- Always read CoreRpcError.kind and .data, never .message alone — the message can be the empty fallback while data holds the typed reason
- Keep DEBUG=core-rpc:error enabled in dev builds; it logs the full json.error frame before throwing
- Keep frontend and core versions in lockstep (pnpm dev:app builds both) to avoid unknown-method errors
When it happens
Trigger: Any `coreRpcClient.call` / `callCoreRpc` invocation where the core replies HTTP 200 with `{ "error": { "code": N, "message": "" } }` or an error object with no `message` key — e.g. a Rust controller returning an error struct whose message serializes to null, or a serde error mapped to a bare code. The code path first logs the full `json.error` at `core-rpc:error` as 'HTTP error response' with the request id and method.
Common situations: Frontend/core version skew (stale core binary lacking a new method), session expiry where the reason rides in `error.data.kind`, controllers that return `Err` with a unit or empty-string message, auth rejection from the bearer-token gate on `/rpc`.
Related errors
- Core RPC response missing result
- Unknown core RPC error
- Core rejected the meet_agent_list_calls request.
- Core rejected the meet_agent_get_call_detail request.
- Cloud RPC returned an error
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/0be67cfefbc61ffd.
Report an issue: GitHub.