Owners page spams SOCIAL not-found error toasts #150

Closed
opened 2026-09-05 18:30:00 +00:00 by crueber · 3 comments
Owner

Owners page spams "SOCIAL: not found" error toasts

On / (see screenshot): red error toasts SOCIAL:O/R-FORK not found: repo o/r-fork not found and SOCIAL:E2E/DEMO2-FORK not found: repo e2e/demo2-fork not found.

Initial analysis (to verify in the fix):

  • The per-row auxiliary fetches added in #137/#142 (star counts via GET …/api/social, activity stamps via GET …/commits?n=1) surface backend 404s into the error tray instead of failing silently.
  • The failing keys are UPPERCASE (O/R-FORK) while the listed rows are lowercase (o/r-fork) — find where the uppercase key comes from (social fetch keyed off a wrong-cased name? activity stamp? a different listing source?) and fix the source; a fetch for a repo outside the visible list should never happen.
  • Even for genuinely-missing repos, auxiliary per-row data must degrade to placeholder silently (no toast): 404 on social/activity is an expected state (deleted/private/unborn), not an error.

Acceptance criteria

  • No error toasts for expected 404s on social/activity per-row fetches (placeholder/hidden instead).
  • Uppercase phantom keys eliminated at the source (or explained + handled); no fetches for repos not on the page.
  • node --test green; browser check of / with a missing-repo row, both themes, zero toasts + zero console errors; no new deps.
# Owners page spams "SOCIAL:<repo> not found" error toasts On `/` (see screenshot): red error toasts `SOCIAL:O/R-FORK not found: repo o/r-fork not found` and `SOCIAL:E2E/DEMO2-FORK not found: repo e2e/demo2-fork not found`. Initial analysis (to verify in the fix): - The per-row auxiliary fetches added in #137/#142 (star counts via `GET …/api/social`, activity stamps via `GET …/commits?n=1`) surface backend 404s into the error tray instead of failing silently. - The failing keys are UPPERCASE (`O/R-FORK`) while the listed rows are lowercase (`o/r-fork`) — find where the uppercase key comes from (social fetch keyed off a wrong-cased name? activity stamp? a different listing source?) and fix the source; a fetch for a repo outside the visible list should never happen. - Even for genuinely-missing repos, auxiliary per-row data must degrade to placeholder silently (no toast): 404 on social/activity is an expected state (deleted/private/unborn), not an error. ## Acceptance criteria - [ ] No error toasts for expected 404s on social/activity per-row fetches (placeholder/hidden instead). - [ ] Uppercase phantom keys eliminated at the source (or explained + handled); no fetches for repos not on the page. - [ ] `node --test` green; browser check of `/` with a missing-repo row, both themes, zero toasts + zero console errors; no new deps.
Author
Owner

Fix ready for review: #151 (branch fix/issue-150, onto main, not merged). TL;DR root cause: ghost rows are real fork-leftover state (fork.json without child manifest → prefix-listed but manifest-gated reads 404), and the UPPERCASE is just the tray .chip CSS uppercasing the lowercase social:o/r key — no wrong-cased fetch exists. Fix: shared tolerateMissing helper makes 404s on per-row auxiliary fetches silent (star count hidden, stamp shows no-commits-yet). node --test 322 green; browser proof on a seeded scratch stack: 0 toasts dark+light, zero JS exceptions.

Fix ready for review: #151 (branch fix/issue-150, onto main, not merged). TL;DR root cause: ghost rows are real fork-leftover state (fork.json without child manifest → prefix-listed but manifest-gated reads 404), and the UPPERCASE is just the tray .chip CSS uppercasing the lowercase social:o/r key — no wrong-cased fetch exists. Fix: shared tolerateMissing helper makes 404s on per-row auxiliary fetches silent (star count hidden, stamp shows no-commits-yet). node --test 322 green; browser proof on a seeded scratch stack: 0 toasts dark+light, zero JS exceptions.
Author
Owner

PR #151 review (fix/issue-150) — verified in scratch worktree, all claims check out.

ROOT-CAUSE CLAIMS:

  • Ghost rows (fork.json-before-manifest): PLAUSIBLE + VERIFIED in code. runFork (internal/pulls/merge.go:596-608) putCreates repos///fork.json FIRST; child manifest creation is delegated/pending ('manifest share delegated... fork executor pending'). Listing (internal/identity/identity.go:232-251 listRepos) is pure ListPrefixes over repos//, so it names the fork child prefix; social Counts (internal/social/service.go:214-216) is manifest-gated via repoAlive (internal/social/social.go:235-241 Exists on manifest.pb) and 404s 'repo / not found'. Prefix-listed but manifest-missing = ghost row. Mechanism confirmed.
  • Uppercase-as-CSS-uppercase-chip: VERIFIED. App.jsx:90 renders the useData key verbatim inside ; web/src/ui.css:55 .chip carries Tailwind 'uppercase'. So key 'social:o/r-fork' DISPLAYS as 'SOCIAL:O/R-FORK'. No case-folding anywhere: repoName (social.go:221) is plain concat, and no toLowerCase/toUpperCase on the social/commit paths. Fetch itself was always correctly-cased.
  • Key source: key shares full() with request URL — confirmed in StarCount.jsx:30-31 / ActivityStamp.jsx:45-51.

TOLERATEMISSING SEMANTICS (web/src/lib/data.js:77-82):

  • 404-only: checks err?.notFound, and ReposError.notFound (sdk/src/errors.js:25-27) is strictly status===404. Verified each mapping: 401/403/500/TypeError/plain-Error/string all rethrow (pinned by tolerate-missing.test.js 'rethrows every non-404'). A 403 on a private repo still trays as before — no real-error masking. Note: for counts, hiding on 403 would also be defensible, but current behavior (tray) is the conservative choice and matches the doc claim.

AUDIT COMPLETE:

  • Only two per-row fetch sites on / and /:owner: RepoRow (Repos.jsx:18-32, shared by Owners.jsx) = StarCount (social:) + ActivityStamp (activity:). List-level fetches (owners, repos:{owner}) are 200-[]-on-unknown, not per-row probes. No other useData-with-tray on those list pages. Audit claim holds.

PLACEHOLDER BEHAVIOR SANE:

  • StarCount: undefined=loading -> (...) placeholder; null=missing -> hidden (nested Show, no stale placeholder). 0 stars still renders '(0 ⭐)' (fmtStars(0) truthy) — unchanged. ActivityStamp: 404 -> {commits: []} -> 'no commits yet', identical to prior unborn-HEAD mapping (now via shared helper — no behavior change for empty repos).

LAWS: law 1 (no package.json/lock change — 5 files only, no new deps), law 7 (404 -> explicit empty/hidden state, real errors still tray — compliant), law 8 (no new seams, component-level mapping only), law 12 (decision appended to 12_web_ui.md in same change). No Go changes, so no vet/cover impact.

TESTS (scratch worktree @5370d7a; node_modules symlinked from main worktree since worktrees don't carry ignored dirs):

  • node --test web/test/unit/*.test.js: 322 pass, 0 fail (incl. 5 new tolerate-missing tests).
  • vite build: clean (121 modules, built in ~1.5s).
  • No browser drive per review instructions (node tests + code reasoning); AGENTS.md ladder browser step noted as not run.

No fixes needed — nothing to push.

MERGE RECOMMENDATION: ready to merge.

PR #151 review (fix/issue-150) — verified in scratch worktree, all claims check out. ROOT-CAUSE CLAIMS: - Ghost rows (fork.json-before-manifest): PLAUSIBLE + VERIFIED in code. runFork (internal/pulls/merge.go:596-608) putCreates repos/<o>/<r>/fork.json FIRST; child manifest creation is delegated/pending ('manifest share delegated... fork executor pending'). Listing (internal/identity/identity.go:232-251 listRepos) is pure ListPrefixes over repos/<o>/, so it names the fork child prefix; social Counts (internal/social/service.go:214-216) is manifest-gated via repoAlive (internal/social/social.go:235-241 Exists on manifest.pb) and 404s 'repo <o>/<r> not found'. Prefix-listed but manifest-missing = ghost row. Mechanism confirmed. - Uppercase-as-CSS-uppercase-chip: VERIFIED. App.jsx:90 renders the useData key verbatim inside <span class='chip'>; web/src/ui.css:55 .chip carries Tailwind 'uppercase'. So key 'social:o/r-fork' DISPLAYS as 'SOCIAL:O/R-FORK'. No case-folding anywhere: repoName (social.go:221) is plain concat, and no toLowerCase/toUpperCase on the social/commit paths. Fetch itself was always correctly-cased. - Key source: key shares full() with request URL — confirmed in StarCount.jsx:30-31 / ActivityStamp.jsx:45-51. TOLERATEMISSING SEMANTICS (web/src/lib/data.js:77-82): - 404-only: checks err?.notFound, and ReposError.notFound (sdk/src/errors.js:25-27) is strictly status===404. Verified each mapping: 401/403/500/TypeError/plain-Error/string all rethrow (pinned by tolerate-missing.test.js 'rethrows every non-404'). A 403 on a private repo still trays as before — no real-error masking. Note: for counts, hiding on 403 would also be defensible, but current behavior (tray) is the conservative choice and matches the doc claim. AUDIT COMPLETE: - Only two per-row fetch sites on / and /:owner: RepoRow (Repos.jsx:18-32, shared by Owners.jsx) = StarCount (social:) + ActivityStamp (activity:). List-level fetches (owners, repos:{owner}) are 200-[]-on-unknown, not per-row probes. No other useData-with-tray on those list pages. Audit claim holds. PLACEHOLDER BEHAVIOR SANE: - StarCount: undefined=loading -> (...) placeholder; null=missing -> hidden (nested Show, no stale placeholder). 0 stars still renders '(0 ⭐)' (fmtStars(0) truthy) — unchanged. ActivityStamp: 404 -> {commits: []} -> 'no commits yet', identical to prior unborn-HEAD mapping (now via shared helper — no behavior change for empty repos). LAWS: law 1 (no package.json/lock change — 5 files only, no new deps), law 7 (404 -> explicit empty/hidden state, real errors still tray — compliant), law 8 (no new seams, component-level mapping only), law 12 (decision appended to 12_web_ui.md in same change). No Go changes, so no vet/cover impact. TESTS (scratch worktree @5370d7a; node_modules symlinked from main worktree since worktrees don't carry ignored dirs): - node --test web/test/unit/*.test.js: 322 pass, 0 fail (incl. 5 new tolerate-missing tests). - vite build: clean (121 modules, built in ~1.5s). - No browser drive per review instructions (node tests + code reasoning); AGENTS.md ladder browser step noted as not run. No fixes needed — nothing to push. MERGE RECOMMENDATION: ready to merge.
Author
Owner

Fixed by PR #151 (review: ghost-row mechanism + CSS-uppercase confirmed, 404-only tolerance verified; 322/322 node tests), merged. Closing.

Fixed by PR #151 (review: ghost-row mechanism + CSS-uppercase confirmed, 404-only tolerance verified; 322/322 node tests), merged. Closing.
crueber added this to the v1 milestone 2026-09-10 22:27:17 +00:00
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
crueber/walhub#150
No description provided.