Indexer offline: frontend has no user-visible signal when :3100 is unreachable, silently spams 100+ failed requests #96

Closed
opened 2026-04-30 03:42:24 +00:00 by Brouie · 20 comments
Brouie commented 2026-04-30 03:42:24 +00:00 (Migrated from gitlab.com)

Summary

When the YO indexer (:3100) becomes unreachable mid-session, the frontend silently spams hundreds of net::ERR_CONNECTION_REFUSED requests with no user-visible indication that indexer-derived data is stale or offline. The "Indexer v1.8.0 · latest indexed block N · live" status banner that normally appears at the bottom of every route is simply gone — there is no "Indexer offline" badge, no "Reconnecting..." copy, and no stale-data warning.

Repro

  1. Stack 282eb62 up (SKIP+KUMBAYA+NO_COOLDOWN), Vite on 5173, sale live, MetaMask on Chain 31337
  2. Confirm /timecurve is healthy: timer ticking, indexer status banner visible at bottom showing "Indexer v1.8.0 · latest indexed block N · live"
  3. Drop the SSH tunnel forwarding for 3100 → 3100 (kill the indexer port forward only, leave 8545 + 5173 alone)
  4. Wait ~5 seconds for the next indexer poll cycle
  5. Open DevTools console

Observed

  • Console: 155+ errors in ~10 seconds, all net::ERR_CONNECTION_REFUSED on URLs like:
    • http://127.0.0.1:3100/v1/timecurve/chain-timer
    • http://127.0.0.1:3100/v1/timecurve/buys?limit=3&offset=0
    • Repeating aggressively, no apparent backoff
  • Page UI: No visible change. The indexer status banner that normally reads "Indexer v1.8.0 · latest indexed block N · live" is just absent — no "offline" replacement, no error state, no stale badge.
  • Recent Buys panel: Shows "Waiting for the first buy of this round" — identical to the empty state when there genuinely are zero buys. Indistinguishable from "indexer offline + couldn't fetch buy list".
  • RPC-derived reads still work: Timer ticks, current price reads, live band reads, wallet balance, charmWeight reads, BUY CHARM button stays clickable. Anything that goes through the chain RPC at 8545 is fine.

Why this matters

Indexer-derived data is mainly:

  • Recent Buys feed (Live ticker)
  • Indexer mirror panel for fee distributions (Canonical fee sinks "Recent fee distributions" rows)
  • Latest indexed block status banner
  • Battle Feed on Arena page (likely)
  • Podium / leaderboard data on Arena page (likely)

A user with degraded indexer connectivity:

  • Sees "Waiting for the first buy" and may assume they're early when there are actually 100+ buys (just can't fetch them)
  • Sees no Recent fee distributions and may assume the protocol isn't routing fees yet
  • Has no signal to refresh, switch RPC, restart wallet, etc. — just silent emptiness

At TGE this becomes a real risk:

  • A user mistakenly thinks no one's buying yet and waits — meanwhile the band is moving against them
  • Or assumes the protocol broke and FUDs in TG / discord

Plus the 155+ console errors in seconds is itself concerning — aggressive polling without circuit-breaker / exponential backoff hammers the indexer once it comes back up too.

Suggested resolution options

Option A — explicit "Indexer offline" banner. When indexer fetches fail N times in a row (e.g., 3 consecutive), replace the "Indexer v1.8.0 · live" status text with "Indexer offline · retrying" in red/orange. Surface in the same footer location it currently uses.

Option B — stale-data badges on indexer-derived panels. "Recent Buys" panel shows a "Last updated Xs ago · cannot reach indexer" subtitle when fetches start failing. Same for Battle Feed, Recent fee distributions.

Option C — exponential backoff + circuit breaker. After N consecutive failures, throttle from "every block" to "every 30s, then 60s, then 120s" with auto-recovery on first success. Reduces console spam + indexer DDoS-on-recovery.

Option D — distinguish empty state from offline state in copy. "Waiting for the first buy of this round" should only show when indexer is live AND has zero rows. When indexer is offline or fetches are failing, show "Cannot reach indexer · cached data may be stale" instead.

A + C + D together is the strongest fix. Single-issue scope, but fix probably touches the indexer client / hooks layer.

Severity

MEDIUM. Not a launch-blocker (RPC-derived buys still work), but is a real user-trust gap that becomes more painful at TGE. Console pollution + unclear empty states + no offline signal stack together.

Reference

Caught during F-14 walkthrough on /timecurve Simple. Reproducible deterministically by killing port 3100 routing.

cc @PlasticDigits

## Summary When the YO indexer (`:3100`) becomes unreachable mid-session, the frontend silently spams hundreds of `net::ERR_CONNECTION_REFUSED` requests with **no user-visible indication** that indexer-derived data is stale or offline. The "Indexer v1.8.0 · latest indexed block N · live" status banner that normally appears at the bottom of every route is simply gone — there is no "Indexer offline" badge, no "Reconnecting..." copy, and no stale-data warning. ## Repro 1. Stack `282eb62` up (SKIP+KUMBAYA+NO_COOLDOWN), Vite on 5173, sale live, MetaMask on Chain 31337 2. Confirm `/timecurve` is healthy: timer ticking, indexer status banner visible at bottom showing "Indexer v1.8.0 · latest indexed block N · live" 3. Drop the SSH tunnel forwarding for `3100 → 3100` (kill the indexer port forward only, leave 8545 + 5173 alone) 4. Wait ~5 seconds for the next indexer poll cycle 5. Open DevTools console ## Observed - **Console:** 155+ errors in ~10 seconds, all `net::ERR_CONNECTION_REFUSED` on URLs like: - `http://127.0.0.1:3100/v1/timecurve/chain-timer` - `http://127.0.0.1:3100/v1/timecurve/buys?limit=3&offset=0` - Repeating aggressively, no apparent backoff - **Page UI:** No visible change. The indexer status banner that normally reads "Indexer v1.8.0 · latest indexed block N · live" is just absent — no "offline" replacement, no error state, no stale badge. - **Recent Buys panel:** Shows "Waiting for the first buy of this round" — identical to the empty state when there genuinely are zero buys. Indistinguishable from "indexer offline + couldn't fetch buy list". - **RPC-derived reads still work:** Timer ticks, current price reads, live band reads, wallet balance, charmWeight reads, BUY CHARM button stays clickable. Anything that goes through the chain RPC at 8545 is fine. ## Why this matters Indexer-derived data is mainly: - Recent Buys feed (Live ticker) - Indexer mirror panel for fee distributions (Canonical fee sinks "Recent fee distributions" rows) - Latest indexed block status banner - Battle Feed on Arena page (likely) - Podium / leaderboard data on Arena page (likely) A user with degraded indexer connectivity: - Sees "Waiting for the first buy" and may assume they're early when there are actually 100+ buys (just can't fetch them) - Sees no Recent fee distributions and may assume the protocol isn't routing fees yet - Has no signal to refresh, switch RPC, restart wallet, etc. — just silent emptiness At TGE this becomes a real risk: - A user mistakenly thinks no one's buying yet and waits — meanwhile the band is moving against them - Or assumes the protocol broke and FUDs in TG / discord Plus the 155+ console errors in seconds is itself concerning — aggressive polling without circuit-breaker / exponential backoff hammers the indexer once it comes back up too. ## Suggested resolution options **Option A — explicit "Indexer offline" banner.** When indexer fetches fail N times in a row (e.g., 3 consecutive), replace the "Indexer v1.8.0 · live" status text with "Indexer offline · retrying" in red/orange. Surface in the same footer location it currently uses. **Option B — stale-data badges on indexer-derived panels.** "Recent Buys" panel shows a "Last updated Xs ago · cannot reach indexer" subtitle when fetches start failing. Same for Battle Feed, Recent fee distributions. **Option C — exponential backoff + circuit breaker.** After N consecutive failures, throttle from "every block" to "every 30s, then 60s, then 120s" with auto-recovery on first success. Reduces console spam + indexer DDoS-on-recovery. **Option D — distinguish empty state from offline state in copy.** "Waiting for the first buy of this round" should only show when indexer is live AND has zero rows. When indexer is offline or fetches are failing, show "Cannot reach indexer · cached data may be stale" instead. A + C + D together is the strongest fix. Single-issue scope, but fix probably touches the indexer client / hooks layer. ## Severity **MEDIUM.** Not a launch-blocker (RPC-derived buys still work), but is a real user-trust gap that becomes more painful at TGE. Console pollution + unclear empty states + no offline signal stack together. ## Reference Caught during F-14 walkthrough on `/timecurve` Simple. Reproducible deterministically by killing port 3100 routing. cc @PlasticDigits
PlasticDigits commented 2026-04-30 03:50:53 +00:00 (Migrated from gitlab.com)

mentioned in commit 1a603efd4a

mentioned in commit 1a603efd4a25bc816e02b32f60174f6137618237
PlasticDigits commented 2026-04-30 03:51:06 +00:00 (Migrated from gitlab.com)

Implemented Options A + C + D from the issue description (merged to main in commit 1a603ef).

What changed

  • Option A — explicit offline banner: After a debounced failure streak (≥3 distinct wall-clock seconds with at least one failed indexer HTTP attempt), IndexerStatusBar shows Indexer offline · retrying (new error-toned pill). /timecurve hides the global footer, so the same pill is rendered above Recent buys on Simple.
  • Option C — backoff: Shared reportIndexerFetchAttempt / getIndexerBackoffPollMs — healthy intervals stay fast (e.g. ~1s chain-timer, 3s status, 5s/3s buys); after the streak opens, polls step 30s → 60s → 120s until the next success resets. getJson / fetchTimecurveChainTimer now swallow network errors as null to avoid unhandled rejections.
  • Option D — empty copy: Recent buys shows Cannot reach indexer · cached data may be stale when offline or the last poll failed; Waiting for the first buy… only when the last poll succeeded with zero rows and connectivity is healthy. Non-empty cached rows show a stale hint when appropriate.

Automated tests

frontend: `npm test -- --run` (includes new `indexerConnectivity.test.ts`) and `npm run build` — green locally.

Verification checklist for @brouie

  1. Stack with indexer + Vite; /timecurve shows Indexer v… · live (pill above Recent buys).
  2. Kill indexer / block :3100 only; after ~3–5s, pill → Indexer offline · retrying on Simple and footer routes (e.g. Arena).
  3. DevTools Network: indexer requests slow (≥30s gaps) while offline, not a tight 1s/3s hammer.
  4. Recent buys empty: Cannot reach indexer…, not Waiting for the first buy…; with prior rows, list stays + stale hint.
  5. Restore indexer: pill returns live, intervals return to normal.

Leaving the issue open for your sign-off.

Implemented **Options A + C + D** from the issue description (merged to `main` in commit 1a603ef). ### What changed - **Option A — explicit offline banner:** After a debounced failure streak (≥3 distinct wall-clock seconds with at least one failed indexer HTTP attempt), **`IndexerStatusBar`** shows **Indexer offline · retrying** (new error-toned pill). **`/timecurve`** hides the global footer, so the **same** pill is rendered above **Recent buys** on Simple. - **Option C — backoff:** Shared **`reportIndexerFetchAttempt` / `getIndexerBackoffPollMs`** — healthy intervals stay fast (e.g. ~1s chain-timer, 3s status, 5s/3s buys); after the streak opens, polls step **30s → 60s → 120s** until the next success resets. **`getJson`** / **`fetchTimecurveChainTimer`** now swallow network errors as `null` to avoid unhandled rejections. - **Option D — empty copy:** **Recent buys** shows **Cannot reach indexer · cached data may be stale** when offline or the last poll failed; **Waiting for the first buy…** only when the last poll succeeded with **zero** rows and connectivity is healthy. Non-empty cached rows show a stale hint when appropriate. ### Docs / agent cross-links - [docs/frontend/timecurve-views.md#indexer-offline-ux-issue-96](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/frontend/timecurve-views.md#indexer-offline-ux-issue-96) - [docs/testing/invariants-and-business-logic.md#indexer-offline-ux-and-backoff-gitlab-96](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/docs/testing/invariants-and-business-logic.md#indexer-offline-ux-and-backoff-gitlab-96) - Play skill: [skills/verify-yo-indexer-offline-ux/SKILL.md](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/skills/verify-yo-indexer-offline-ux/SKILL.md) - Contributor guardrail **#29** in [.cursor/skills/yieldomega-guardrails/SKILL.md](https://gitlab.com/PlasticDigits/yieldomega/-/blob/main/.cursor/skills/yieldomega-guardrails/SKILL.md) ### Automated tests `frontend`: \`npm test -- --run\` (includes new \`indexerConnectivity.test.ts\`) and \`npm run build\` — green locally. ### Verification checklist for @brouie 1. Stack with indexer + Vite; **`/timecurve`** shows **Indexer v… · live** (pill above Recent buys). 2. Kill indexer / block **:3100** only; after ~3–5s, pill → **Indexer offline · retrying** on Simple and footer routes (e.g. Arena). 3. DevTools Network: indexer requests **slow** (≥30s gaps) while offline, not a tight 1s/3s hammer. 4. **Recent buys** empty: **Cannot reach indexer…**, not **Waiting for the first buy…**; with prior rows, list stays + stale hint. 5. Restore indexer: pill returns **live**, intervals return to normal. Leaving the issue **open** for your sign-off.
Brouie commented 2026-04-30 04:21:08 +00:00 (Migrated from gitlab.com)

mentioned in issue #38

mentioned in issue #38
PlasticDigits commented 2026-04-30 05:25:10 +00:00 (Migrated from gitlab.com)

mentioned in issue #100

mentioned in issue #100
Brouie commented 2026-04-30 06:53:45 +00:00 (Migrated from gitlab.com)

Partial verification on 1a603ef ... dd1c59a HEAD today. Items 2-6 deferred until Item 1 (baseline) is resolved.

Item 1 — Baseline pill on /timecurve Simple — FAIL

Stack up cleanly: indexer at 127.0.0.1:3100 returning /v1/status 200 with schema_version=1.8.0, max_indexed_block=12, database_connected=true. /v1/timecurve/buys populated with the live buy from block 12 (deployer 5 CHARM minted, 5.092 CL8Y spent, +120s, 250 BP).

But on /timecurve Simple page in the browser:

  • No "Indexer v1.8.0 · latest indexed block N · live" pill above "Recent buys"
  • No global footer pill at the bottom either
  • DOM inspection (Elements panel, Ctrl+F search for class="indexer-status*") returns 0 matches on Simple

Confirmed working on /timecurve/arena and /timecurve/protocol: both routes render the indexer status banner correctly (live state, block number, schema version).

The fix description says:

"Option A — explicit offline banner: ... IndexerStatusBar shows ... /timecurve hides the global footer, so the same pill is rendered above Recent buys on Simple."

Right now Simple has neither — global footer is correctly hidden but the inline-above-Recent-buys replacement pill is not rendering. So the baseline (Item 1 of the SKILL.md) cannot be confirmed visually on Simple.

Items 2-6 — Deferred until Item 1 resolves

Without a working baseline pill on Simple, I cannot verify the offline-banner state transition (Item 3) or the empty-state copy distinguishing offline vs live-zero-rows (Item 5). Will resume once the Simple-page pill rendering is fixed.

The other gated routes (Arena, Protocol) seem to render the IndexerStatusBar correctly so the offline detection logic + backoff likely work end-to-end there. Could spot-check Items 2-6 against Arena instead if you'd prefer that path while Simple is being investigated.

cc @PlasticDigits

Partial verification on `1a603ef` ... `dd1c59a` HEAD today. Items 2-6 deferred until Item 1 (baseline) is resolved. ## Item 1 — Baseline pill on `/timecurve` Simple — FAIL Stack up cleanly: indexer at 127.0.0.1:3100 returning `/v1/status` 200 with `schema_version=1.8.0`, `max_indexed_block=12`, `database_connected=true`. `/v1/timecurve/buys` populated with the live buy from block 12 (deployer 5 CHARM minted, 5.092 CL8Y spent, +120s, 250 BP). But on `/timecurve` Simple page in the browser: - No "Indexer v1.8.0 · latest indexed block N · live" pill above "Recent buys" - No global footer pill at the bottom either - DOM inspection (Elements panel, Ctrl+F search for `class="indexer-status*"`) returns 0 matches on Simple Confirmed working on `/timecurve/arena` and `/timecurve/protocol`: both routes render the indexer status banner correctly (live state, block number, schema version). The fix description says: > "Option A — explicit offline banner: ... `IndexerStatusBar` shows ... `/timecurve` hides the global footer, so the **same** pill is rendered above **Recent buys** on Simple." Right now Simple has neither — global footer is correctly hidden but the inline-above-Recent-buys replacement pill is not rendering. So the baseline (Item 1 of the SKILL.md) cannot be confirmed visually on Simple. ## Items 2-6 — Deferred until Item 1 resolves Without a working baseline pill on Simple, I cannot verify the offline-banner state transition (Item 3) or the empty-state copy distinguishing offline vs live-zero-rows (Item 5). Will resume once the Simple-page pill rendering is fixed. The other gated routes (Arena, Protocol) seem to render the IndexerStatusBar correctly so the offline detection logic + backoff likely work end-to-end there. Could spot-check Items 2-6 against Arena instead if you'd prefer that path while Simple is being investigated. cc @PlasticDigits
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-04-30 08:18:30 +00:00
PlasticDigits commented 2026-04-30 08:18:31 +00:00 (Migrated from gitlab.com)

Pill removed from simple page to keep ux simple - its already complex, so any additional info (like indexer) will cause more user confusion beyond any benefit. closing.

Pill removed from simple page to keep ux simple - its already complex, so any additional info (like indexer) will cause more user confusion beyond any benefit. closing.
PlasticDigits (Migrated from gitlab.com) reopened this issue 2026-04-30 08:18:37 +00:00
PlasticDigits commented 2026-04-30 08:19:05 +00:00 (Migrated from gitlab.com)

@Brouie Reopening because I see items 2 thru 6 still need checking. Please skip Item 1, as noted it is intentionally removed from the Simple page as the Simple page is supposed to be kept as minimal as possible, and the indexer information is not necessary for the user under normal operating conditions.

@Brouie Reopening because I see items 2 thru 6 still need checking. Please skip Item 1, as noted it is intentionally removed from the Simple page as the Simple page is supposed to be kept as minimal as possible, and the indexer information is not necessary for the user under normal operating conditions.
Brouie commented 2026-05-01 14:57:53 +00:00 (Migrated from gitlab.com)

Source-level review on 1a603ef (carried into 243e2a0). Acknowledging your reopen — Item 1 skipped per your direction (pill intentionally absent on Simple to keep UX minimal).

Source-level findings on items 2-5

  • Item 3: backoff intervals correct — src/lib/indexerConnectivity.ts:
    • INDEXER_OFFLINE_FAILURE_STREAK = 3 (matches "≥3 distinct wall-clock seconds" in your spec)
    • BACKOFF_MS = [30_000, 60_000, 120_000] — exact 30s → 60s → 120s tiers
    • Tier saturates at index 2 (120s) for 4th+ failures via Math.min(streak - 3, BACKOFF_MS.length - 1)
    • resetIndexerConnectivityForTests() test-mode reset hook present
    • indexerConnectivity.test.ts: 5/5 tests PASS in 4ms (tier math + streak counting + per-second debounce + success reset + offline threshold transition).
  • Item 4: empty-state copy distinction — TimeCurveSimplePage.tsx:1359-1364:
    buyPollLastOk === true && recentBuys && recentBuys.length === 0 && !isOffline
      ? "Waiting for the first buy of this round."   // genuine empty
      : buyPollLastOk === false || isOffline
      ? "Cannot reach indexer · cached data may be stale"   // offline / failed poll
      : "Loading recent buys…"
    
    Three-condition gate (buyPollLastOk === true AND length === 0 AND !isOffline) correctly limits the "Waiting for the first buy" copy to your stated case.
  • Item 5 partial: recovery path — reportIndexerFetchAttempt(true) in the success branches (Arena model line 263, Simple page line 360, hero timer line 97) resets failureStreak to 0, which getIndexerBackoffPollMs consults — intervals return to fast on first successful poll.

cc @PlasticDigits

Source-level review on `1a603ef` (carried into `243e2a0`). Acknowledging your reopen — Item 1 skipped per your direction (pill intentionally absent on Simple to keep UX minimal). ### Source-level findings on items 2-5 - [x] **Item 3: backoff intervals correct** — `src/lib/indexerConnectivity.ts`: - `INDEXER_OFFLINE_FAILURE_STREAK = 3` (matches "≥3 distinct wall-clock seconds" in your spec) - `BACKOFF_MS = [30_000, 60_000, 120_000]` — exact 30s → 60s → 120s tiers - Tier saturates at index 2 (120s) for 4th+ failures via `Math.min(streak - 3, BACKOFF_MS.length - 1)` - `resetIndexerConnectivityForTests()` test-mode reset hook present - `indexerConnectivity.test.ts`: 5/5 tests PASS in 4ms (tier math + streak counting + per-second debounce + success reset + offline threshold transition). - [x] **Item 4: empty-state copy distinction** — `TimeCurveSimplePage.tsx:1359-1364`: ```tsx buyPollLastOk === true && recentBuys && recentBuys.length === 0 && !isOffline ? "Waiting for the first buy of this round." // genuine empty : buyPollLastOk === false || isOffline ? "Cannot reach indexer · cached data may be stale" // offline / failed poll : "Loading recent buys…" ``` Three-condition gate (`buyPollLastOk === true` AND `length === 0` AND `!isOffline`) correctly limits the "Waiting for the first buy" copy to your stated case. - [x] **Item 5 partial: recovery path** — `reportIndexerFetchAttempt(true)` in the success branches (Arena model line 263, Simple page line 360, hero timer line 97) resets `failureStreak` to 0, which `getIndexerBackoffPollMs` consults — intervals return to fast on first successful poll. cc @PlasticDigits
PlasticDigits (Migrated from gitlab.com) closed this issue 2026-05-02 04:36:26 +00:00
PlasticDigits commented 2026-05-03 10:47:52 +00:00 (Migrated from gitlab.com)

mentioned in issue #115

mentioned in issue #115
Brouie commented 2026-05-04 02:42:58 +00:00 (Migrated from gitlab.com)

live walkthrough done. items 2-5 + recovery all pass.

setup: full anvil + indexer + vite stack on the same fresh deploy as #114/#115/#101. killed indexer process yieldomega-indexer, observed offline state on browser, restarted indexer, observed recovery without reload.

item 2 (backoff working): post-kill saw ~38 indexer fetch errors spread over 6+ wall-clock seconds, NOT the 155+ in 10s spam from the original repro. polls correctly stepping into 30s/60s/120s tiers per the streak gate.

item 3 (offline state triggers): with indexer dead, Arena page shows chain-timer fallback (TIME REMAINING displays em-dash + "Loading on-chain deadline…" + "Timer pressure will appear once the sale is readable from chain."), reserve podiums show "Loading the four onchain podium categories…", LIVE BUYS panel shows leprechaun + "Could not load buys from the indexer (offline, CORS, or HTTP error). Check the indexer is running." wallet-connected reads (CL8Y balance 100m, 1 CHARM live price 1.001646 CL8Y) keep working since those go through chain RPC at 8545.

item 4 (empty vs offline distinction): confirmed the distinct copy. with indexer dead → "Could not load buys from the indexer (offline, CORS, or HTTP error). Check the indexer is running." with indexer alive + zero indexed buys → "No buys indexed yet." two genuinely different paragraphs, not just a state flag.

item 5 (recovery): restarted indexer, page transitioned back to success state without a refresh. TIME REMAINING regained digits (23:35:39 ticking on the deadline countdown), LIVE BUYS card flipped from offline copy to "No buys indexed yet." empty-state copy, footer IndexerStatusBar showed "Indexer v1.11.0 · latest indexed block 10 · live". rivalry feed even surfaced the events from earlier in the session ("WarBow burn — You paid the PvP burn" + "WarBow defense — You activated guard" at block 10) once indexing caught up.

item 6 (visual confirmation): confirmed on /timecurve (Simple, IndexerStatusBar correctly hidden per your intentional design — fallback copy in Recent buys panel does the work) and /timecurve/arena (full IndexerStatusBar in footer + chain-timer fallback). Protocol path uses the same global IndexerStatusBar so behavior is shared.

item 1 skipped per your reopen note (Simple page pill intentionally absent to keep ux minimal). all 5 remaining items pass.

live walkthrough done. items 2-5 + recovery all pass. **setup**: full anvil + indexer + vite stack on the same fresh deploy as #114/#115/#101. killed indexer process `yieldomega-indexer`, observed offline state on browser, restarted indexer, observed recovery without reload. **item 2 (backoff working)**: post-kill saw ~38 indexer fetch errors spread over 6+ wall-clock seconds, NOT the 155+ in 10s spam from the original repro. polls correctly stepping into 30s/60s/120s tiers per the streak gate. **item 3 (offline state triggers)**: with indexer dead, Arena page shows chain-timer fallback (TIME REMAINING displays em-dash + "Loading on-chain deadline…" + "Timer pressure will appear once the sale is readable from chain."), reserve podiums show "Loading the four onchain podium categories…", LIVE BUYS panel shows leprechaun + "Could not load buys from the indexer (offline, CORS, or HTTP error). Check the indexer is running." wallet-connected reads (CL8Y balance 100m, 1 CHARM live price 1.001646 CL8Y) keep working since those go through chain RPC at 8545. **item 4 (empty vs offline distinction)**: confirmed the distinct copy. with indexer dead → "Could not load buys from the indexer (offline, CORS, or HTTP error). Check the indexer is running." with indexer alive + zero indexed buys → "No buys indexed yet." two genuinely different paragraphs, not just a state flag. **item 5 (recovery)**: restarted indexer, page transitioned back to success state without a refresh. TIME REMAINING regained digits (23:35:39 ticking on the deadline countdown), LIVE BUYS card flipped from offline copy to "No buys indexed yet." empty-state copy, footer IndexerStatusBar showed "Indexer v1.11.0 · latest indexed block 10 · live". rivalry feed even surfaced the events from earlier in the session ("WarBow burn — You paid the PvP burn" + "WarBow defense — You activated guard" at block 10) once indexing caught up. **item 6 (visual confirmation)**: confirmed on /timecurve (Simple, IndexerStatusBar correctly hidden per your intentional design — fallback copy in Recent buys panel does the work) and /timecurve/arena (full IndexerStatusBar in footer + chain-timer fallback). Protocol path uses the same global IndexerStatusBar so behavior is shared. item 1 skipped per your reopen note (Simple page pill intentionally absent to keep ux minimal). all 5 remaining items pass.
PlasticDigits commented 2026-05-21 05:42:47 +00:00 (Migrated from gitlab.com)

mentioned in issue #231

mentioned in issue #231
PlasticDigits commented 2026-05-21 13:21:02 +00:00 (Migrated from gitlab.com)

mentioned in issue #234

mentioned in issue #234
PlasticDigits commented 2026-05-27 07:07:47 +00:00 (Migrated from gitlab.com)

mentioned in issue #258

mentioned in issue #258
PlasticDigits commented 2026-05-27 14:33:22 +00:00 (Migrated from gitlab.com)

mentioned in issue #262

mentioned in issue #262
PlasticDigits commented 2026-05-29 03:24:01 +00:00 (Migrated from gitlab.com)

mentioned in issue #263

mentioned in issue #263
PlasticDigits commented 2026-06-03 13:37:20 +00:00 (Migrated from gitlab.com)

mentioned in merge request !414

mentioned in merge request !414
PlasticDigits commented 2026-06-25 14:28:40 +00:00 (Migrated from gitlab.com)

mentioned in issue #342

mentioned in issue #342
PlasticDigits commented 2026-06-25 20:07:12 +00:00 (Migrated from gitlab.com)

mentioned in issue #343

mentioned in issue #343
PlasticDigits commented 2026-06-25 20:07:35 +00:00 (Migrated from gitlab.com)

mentioned in issue #354

mentioned in issue #354
PlasticDigits commented 2026-06-25 22:29:38 +00:00 (Migrated from gitlab.com)

mentioned in merge request !522

mentioned in merge request !522
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
code/yieldomega#96
No description provided.