From 430daca591f81dc9b89e33702e68be12af7c5ea2 Mon Sep 17 00:00:00 2001 From: giwaov Date: Sun, 28 Jun 2026 12:39:12 +0100 Subject: [PATCH] Handle empty validator set in monitoring --- cmd/rpc/web/wallet/src/core/dsCore.ts | 22 +++++++++++++++++++++- cmd/rpc/web/wallet/src/hooks/useNodes.ts | 13 ++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/cmd/rpc/web/wallet/src/core/dsCore.ts b/cmd/rpc/web/wallet/src/core/dsCore.ts index a420f7ee36..baedaecd9e 100644 --- a/cmd/rpc/web/wallet/src/core/dsCore.ts +++ b/cmd/rpc/web/wallet/src/core/dsCore.ts @@ -167,7 +167,27 @@ export async function fetchDsOnce(chain: ChainLike, key: string, ctx?: Re const { url, init } = buildRequest(chain, leaf, ctx) if (!url) throw new Error(`Invalid DS url for key ${key}`) const res = await fetch(url, init) - if (!res.ok) throw new Error(`RPC ${res.status}`) + if (!res.ok) { + const ct = res.headers.get('content-type') || '' + let response: any + try { + response = ct.includes('application/json') ? await res.json() : await res.text() + } catch { + response = undefined + } + + const message = + response && typeof response === 'object' && 'msg' in response + ? `RPC ${res.status}: ${response.msg}` + : `RPC ${res.status}` + + throw Object.assign(new Error(message), { + status: res.status, + code: response && typeof response === 'object' ? response.code : undefined, + module: response && typeof response === 'object' ? response.module : undefined, + response, + }) + } const parsed = await parseResponse(res, leaf) return parsed as T } diff --git a/cmd/rpc/web/wallet/src/hooks/useNodes.ts b/cmd/rpc/web/wallet/src/hooks/useNodes.ts index 5ec7515592..a3be9650c4 100644 --- a/cmd/rpc/web/wallet/src/hooks/useNodes.ts +++ b/cmd/rpc/web/wallet/src/hooks/useNodes.ts @@ -31,6 +31,12 @@ export interface NodeData { validatorSet: any; } +const isNoValidatorsError = (error: unknown): boolean => + typeof error === "object" && + error !== null && + "code" in error && + Number((error as { code?: unknown }).code) === 29; + /** * Hook to fetch the current chain's committeeId from admin.config */ @@ -156,7 +162,12 @@ export const useNodeData = (nodeId: string) => { dsFetch("admin.consensusInfo"), dsFetch("admin.peerInfo"), dsFetch("admin.resourceUsage"), - dsFetch("validatorSet", { height: 0, committeeId: committeeId! }), + dsFetch("validatorSet", { height: 0, committeeId: committeeId! }).catch((error) => { + if (isNoValidatorsError(error)) { + return { validatorSet: [] }; + } + throw error; + }), ]); return {