diff --git a/dashboard/client/src/api.ts b/dashboard/client/src/api.ts index d8a979c58..767ee4a0d 100644 --- a/dashboard/client/src/api.ts +++ b/dashboard/client/src/api.ts @@ -112,7 +112,7 @@ export type NodeDetails = { } & BaseNodeInfo; export type RayletData = { - // Merger of GCSNodeStats and GetNodeStatsReply + // Merger of GCSNodeInfo and GetNodeStatsReply // GetNodeStatsReply fields. // Note workers are in an array in NodeDetails objectStoreUsedMemory: number; diff --git a/dashboard/client/src/pages/dashboard/node-info/NodeInfo.tsx b/dashboard/client/src/pages/dashboard/node-info/NodeInfo.tsx index 2b1a12c03..c3669eaa2 100644 --- a/dashboard/client/src/pages/dashboard/node-info/NodeInfo.tsx +++ b/dashboard/client/src/pages/dashboard/node-info/NodeInfo.tsx @@ -139,7 +139,12 @@ const useNodeInfoStyles = makeStyles((theme: Theme) => }), ); -const nodesSelector = (state: StoreState) => state.dashboard?.nodeInfo?.clients; +// Dead node payloads don't contain the full information needed to render +// so we filter them out here. +const liveNodesSelector = (state: StoreState) => + state.dashboard?.nodeInfo?.clients.filter( + (node) => node.raylet.state === "ALIVE", + ); type DialogState = { nodeIp: string; @@ -170,7 +175,7 @@ const NodeInfo: React.FC<{}> = () => { const toggleOrder = () => setOrder(order === "asc" ? "desc" : "asc"); const [orderBy, setOrderBy] = React.useState(null); const classes = useNodeInfoStyles(); - const nodes = useSelector(nodesSelector); + const nodes = useSelector(liveNodesSelector); if (!nodes) { return Loading...; }