Skip to content

Fix hydration 404s, Sentry deploy sync, and four open issues - #376

Merged
owens1127 merged 2 commits into
mainfrom
fix/sentry-hydration-deploy-sync
Jun 17, 2026
Merged

Fix hydration 404s, Sentry deploy sync, and four open issues#376
owens1127 merged 2 commits into
mainfrom
fix/sentry-hydration-deploy-sync

Conversation

@owens1127

Copy link
Copy Markdown
Contributor

Summary

  • WEBSITE-4: Fix React Add admin-only blacklist action to PGCR menu #329 hydration crash — use notFound() instead of rendering client <NotFound /> on reserved paths; add bare /profile page; reserve profile/privacy/terms vanity slugs
  • WEBSITE-19: Cap parallel /instance guardian fetches (max 3) and tighten viewport intersection on history clusters
  • WEBSITE-30 / WEBSITE-Z: Drop extension sendMessage noise; treat ApiKeyError as handled and disable Sentry capture on /status probe
  • Deploy: Sync SENTRY_RELEASE with APP_VERSION on prod deploy; post-deploy sync-sentry-release.sh resolves Fixes WEBSITE-* issues in the correct release (uses SENTRY_ISSUE_AUTH_TOKEN)

Issues addressed

WEBSITE-4, WEBSITE-19, WEBSITE-30, WEBSITE-Z

Test plan

  • bun scripts/check-vanity-slugs.mjs
  • bunx tsc --noEmit
  • bun run lint
  • Merge → deploy → curl -I https://raidhub.io/profile / /calendar / /checkpoints return 404
  • Confirm Sentry unresolved count drops and sync step resolves issues in APP_VERSION release

Made with Cursor

Use notFound() instead of embedding the client NotFound page (fixes React
#329 on /profile, /calendar, /checkpoints). Reserve profile/privacy/terms
vanity slugs. Sync SENTRY_RELEASE with APP_VERSION and auto-resolve Fixes
issues post-deploy. Cap parallel /instance guardian fetches; skip extension
and ApiKeyError noise.

Fixes WEBSITE-4, WEBSITE-19, WEBSITE-30, WEBSITE-Z

Co-authored-by: Cursor <cursoragent@cursor.com>
@vercel

vercel Bot commented Jun 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
raid-hub Ready Ready Preview Jun 17, 2026 11:17pm

Request Review

Comment on lines +35 to +45
return true
}
if (claimed.size >= MAX_CONCURRENT_INSTANCE_FETCHES) {
return false
}
setClaimed(prev => new Set(prev).add(instanceId))
bump()
return true
},
[bump, claimed]
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The tryClaim function in useCallback captures a stale claimed state, causing the MAX_CONCURRENT_INSTANCE_FETCHES limit to be bypassed when multiple components claim a fetch budget simultaneously.
Severity: MEDIUM

Suggested Fix

The stale closure issue can be resolved by storing the claimed set in a useRef instead of useState. This ensures that tryClaim always reads the most current value, as refs are mutable and not captured by closures in the same way state is. Alternatively, restructure the claiming logic to avoid reading the state from outside a functional updater.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/components/profile/raids/history/ClusterGuardianFetchBudget.tsx#L32-L45

Potential issue: The `tryClaim` function, defined within a `useCallback`, closes over
the `claimed` state variable. When multiple `ClusterGuardians` components become visible
at once, their effects run in the same React batch. Each effect calls `tryClaim`, but
they all read the same stale snapshot of the `claimed` set. This allows the
`claimed.size >= MAX_CONCURRENT_INSTANCE_FETCHES` check to incorrectly pass for multiple
callers, leading to more than the intended maximum of 3 parallel `/instance` fetches
being dispatched. This defeats the purpose of the fetch budget mechanism.

Did we get this right? 👍 / 👎 to inform future reviews.

Co-authored-by: Cursor <cursoragent@cursor.com>
}) => {
const containerRef = useRef<HTMLDivElement>(null)
const isVisible = useIsVisible(containerRef, { rootMargin: "240px" })
const isVisible = useIsVisible(containerRef, { rootMargin: "0px", threshold: 0.35 })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: An inline object passed to the useIsVisible hook in ClusterGuardians causes a new IntersectionObserver to be created on every render, leading to performance issues.
Severity: MEDIUM

Suggested Fix

To prevent unnecessary re-creations of the IntersectionObserver, the options object should be memoized. Either define the object as a constant outside the component or wrap it with the useMemo hook to ensure its reference remains stable across renders.

Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.

Location: src/components/profile/raids/history/ClusterGuardians.tsx#L21

Potential issue: In the `ClusterGuardians` component, the `useIsVisible` hook is called
with an inline object literal for its `options` parameter. Because this object is a
dependency of a `useEffect` within the hook, a new `IntersectionObserver` is created on
every render of the component. While React 18's state batching prevents an infinite
loop, this pattern is a performance anti-pattern that causes unnecessary work, creating
and tearing down observers repeatedly. This leads to performance degradation, especially
if many of these components are rendered.

@owens1127
owens1127 merged commit 5e76006 into main Jun 17, 2026
7 checks passed
@owens1127
owens1127 deleted the fix/sentry-hydration-deploy-sync branch June 17, 2026 23:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant