Skip to content

fix(watchlist): prevent phantom miners from leaking into watchlist via /miners/details with an unknown id#1157

Open
jack-stormentswe wants to merge 1 commit into
entrius:testfrom
jack-stormentswe:fix/watchlist-phantom-miners
Open

fix(watchlist): prevent phantom miners from leaking into watchlist via /miners/details with an unknown id#1157
jack-stormentswe wants to merge 1 commit into
entrius:testfrom
jack-stormentswe:fix/watchlist-phantom-miners

Conversation

@jack-stormentswe
Copy link
Copy Markdown

@jack-stormentswe jack-stormentswe commented May 14, 2026

Closes #1159

Summary

The Miner Details page renders the "add to watchlist" star button as soon as a githubId is present in the URL - before the underlying miner data has been fetched. This makes it possible to pin a miner that doesn't actually exist (e.g. by manually visiting /miners/details?githubId=123456789), which leaks a phantom entry into the watchlist that can never be opened to anything but a "No data found" error page.

It also produces a visible inconsistency in the watchlist itself: the sidebar/category badge counts every id in storage, but the miners table inner-joins against useAllMiners() and silently drops anything that doesn't resolve - so the badge can read "Watchlist 2" while the visible list shows zero or one miner, with no way for the user to clean up the difference.

The repository and PR/issue detail pages already gate their watchlist buttons behind a successful data fetch - only the miner details page was missing this guard.

Changes

  • src/pages/MinerDetailsPage.tsx - call useMinerStats(githubId) at the page level and render <WatchlistButton> only after the fetch resolves with a real record. While loading, or when the miner is unknown, the star is hidden. (TanStack Query dedupes against the existing call inside MinerScoreCard, so this adds no extra network traffic.)
  • src/pages/WatchlistPage.tsx - MinersList now detects unresolved watched ids (entries that aren't in the all-miners cache once it's loaded) and surfaces them as a warning card with a one-click Remove unresolved action. The visible list is unchanged for resolved miners.

Verification

  1. Open /miners/details?githubId=123456789 in an incognito window. While the request is in flight the star is absent; once the API responds with no record the star stays hidden and the page collapses to the existing "No data found" card. The star can no longer be clicked.
  2. Open a real miner profile (e.g. via the leaderboard). The star renders as before after the page data loads, and toggling it adds/removes the miner from the watchlist exactly as it did previously.
  3. Pre-seed a phantom watchlist entry from DevTools - localStorage.setItem('gittensor.watchlist.v2', JSON.stringify({ miners: ['999999'], repos: [], bounties: [], prs: [], issues: [] })) - then reload /watchlist. The sidebar badge reads "1", and the miners tab now shows a warning card explaining the entry couldn't be loaded with a Remove unresolved button that clears it. Clicking it removes the entry from localStorage and the badge updates to "0".
  4. The unresolved card only appears once useAllMiners() has finished loading, so a slow network won't cause a false positive on first paint.

Recording

83.mp4

@jack-stormentswe
Copy link
Copy Markdown
Author

@anderdc Could you take a look when you have a moment? Thanks!

@xiao-xiao-mao xiao-xiao-mao Bot added the bug Something isn't working label May 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Watchlist can pin a miner that doesn't exist, leaving a phantom entry the user can't clean up

1 participant