Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion packages/brain/src/modules/apiServers/ui/startUiServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ interface RpcRequest {
id: string | number | null;
}

function toRpcErrorMessage(error: unknown): string {
if (error == null) return "Unknown error";
if (typeof error === "string") return error;
if (error instanceof Error) return error.message || error.name || "Unknown error";
try {
return JSON.stringify(error);
} catch {
return String(error);
}
}

export function startUiServer({
brainDb,
blockExplorerApi,
Expand Down Expand Up @@ -101,7 +112,7 @@ export function startUiServer({
logger.error(error);
callback({
jsonrpc: "2.0",
error: { code: -32601, message: error },
error: { code: -32601, message: toRpcErrorMessage(error) },
id
});
}
Expand Down
39 changes: 38 additions & 1 deletion packages/ui/src/socket/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,40 @@ import { io, Socket } from "socket.io-client";
import { RoutesArguments, RoutesReturn, RpcMethodNames } from "./types.js";
import { BRAIN_UI_DOMAIN, Network } from "@stakingbrain/common";

function toErrorMessage(value: unknown): string {
if (value == null) return "Unknown error";
if (typeof value === "string") return value;
if (value instanceof Error) return value.message || value.name || "Unknown error";

if (typeof value === "object") {
const record = value as Record<string, unknown>;
// Common JSON-RPC shape: { code, message, data }
const message = record.message;

if (typeof message === "string") return message;
if (message instanceof Error) return message.message || message.name || "Unknown error";

// In this repo the backend currently sends `message: error` where error can be an object.
if (message && typeof message === "object") {
const nested = message as Record<string, unknown>;
if (typeof nested.message === "string") return nested.message;
try {
return JSON.stringify(message);
} catch {
return String(message);
}
}

try {
return JSON.stringify(value);
} catch {
return String(value);
}
}

return String(value);
}

class RpcClient {
private socket: Socket;

Expand Down Expand Up @@ -33,7 +67,10 @@ class RpcClient {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
this.socket.emit("rpc", rpcRequest, (response: any) => {
if (response.error) {
reject(response.error);
const err = new Error(toErrorMessage(response.error));
// Preserve the raw JSON-RPC error payload for debugging if needed.
(err as Error & { rpcError?: unknown }).rpcError = response.error;
reject(err);
} else {
resolve(response.result as RoutesReturn[T]);
}
Expand Down