From 97f331ae03637f668e664efa2735c16ef80cf0d4 Mon Sep 17 00:00:00 2001 From: Florent Tapponnier Date: Fri, 17 Jul 2026 16:01:36 +0200 Subject: [PATCH] share-card: filter negative p50 in sortByP50 (fixes HTTP 500 on RPC benches) Commit c03c599 relaxed the sortByP50 filter from `p50 > 0` to `p50 !== 0` to support the negative-p50 'warming up' sentinel introduced for funding benches on the /products page. The relaxation leaked into the share-card render path, where negatives crash Satori: negative p50 values fed to Math.max produce a negative maxP50, which inverts every bar height ratio and blows up the JSX with an opaque 'Spread syntax' error mid-render. Symptoms observed: /benchmarks/{rpc-capabilities,polkadot-rpc,ws-head-latency-ethereum,evm-block-builders}/share-card?template=ranking all returning HTTP 500. Working benches (network-coverage, perp-fees, oracle-deviation) had no negative sentinel values in their data. Fix restores `p50 > 0` in the share-card filter. The negative sentinel handling stays on the /products page where it was designed to render (as 'warming up'). Share-card treats negatives as noise and drops them, same as zeros. --- src/app/benchmarks/[slug]/share-card/route.tsx | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/app/benchmarks/[slug]/share-card/route.tsx b/src/app/benchmarks/[slug]/share-card/route.tsx index ad027e4a..6e5465bb 100644 --- a/src/app/benchmarks/[slug]/share-card/route.tsx +++ b/src/app/benchmarks/[slug]/share-card/route.tsx @@ -12,10 +12,15 @@ import { clientKey, rateLimit, tooManyRequests } from "@/lib/rate-limit"; import { SLUG_RE } from "@/lib/slug"; /** Best → worst, depending on whether higher numbers are better. Drops - * rows with missing `ms` or non-positive p50, mirroring /api/stat. Those - * zero-value placeholders blow up the bar layout (NaN heights from a - * divide-by-zero maxP50, ratios > 1) which makes Satori reject the JSX - * with an opaque "Spread syntax" error mid-stream. */ + * rows with missing `ms` or non-positive p50. Both zero and negative + * values must be filtered here: zeros blow up bar heights via + * divide-by-zero maxP50, and negatives (used as a "warming up" + * sentinel on funding benches via commit c03c599) produce a negative + * maxP50 and inverted ratios which makes Satori reject the JSX with + * an opaque "Spread syntax" error mid-stream. The `!== 0` rewrite + * was correct for the /products page (which surfaces the negative + * sentinel explicitly) but leaked into the share-card render path + * where negatives are just noise on the bar chart. */ function sortByP50(b: Benchmark): ProviderResult[] { return [...b.results] .filter( @@ -23,7 +28,7 @@ function sortByP50(b: Benchmark): ProviderResult[] { !!r && !!r.ms && Number.isFinite(r.ms.p50) && - r.ms.p50 !== 0, + r.ms.p50 > 0, ) .sort( b.higherIsBetter