What it does
When something throws an uncaught exception in RemixCRM — a server action, a React tree, anything — the user sees a friendly recovery page instead of a generic "page couldn't load" screen, and the error is automatically filed in your bug-reports inbox with the stack trace, page URL, browser info, and a unique digest ID.
You don't have to ask users to report bugs. They're already reported.
What the user sees
A dark recovery page with:
- "Something went wrong"
- A reassuring message ("We've been notified")
- The error ID (a digest like
3457432882) and the report ID (a1b2c3d4) - Try again button (re-renders the failed segment)
- Go home link
If your user emails you the error ID, you can grep Railway logs for it to find the underlying stack trace.
Where reports show up
In Supabase (or your existing support dashboard), the bug_reports table:
select id, description, page_url, created_at
from bug_reports
where category = 'auto'
order by created_at desc
limit 20;
Auto-reports are tagged category = 'auto' to distinguish them from
user-initiated reports filed via the support chat.
Deduplication
The same error digest from the same page is recorded once per 15 minutes. This prevents a viral bug (e.g. a popular page broken for all users) from generating thousands of duplicate rows. After 15 minutes, a new row is filed so you can tell the difference between "bug we fixed" and "bug came back."
How it works under the hood
- React tree throws
- Next.js renders
app/global-error.tsx(root) orapp/(app)/error.tsx(app routes) - That component fires a
useEffectthat POSTs to/api/auto-error-reportwith the digest, message, stack, page URL, and browser info - The endpoint inserts a
bug_reportsrow withcategory = 'auto' - The dedupe check skips inserts if the same digest + URL was already reported in the last 15 minutes
The POST uses keepalive: true so it survives the user clicking "Go home"
mid-fetch.
What's captured
| Field | Source |
|---|---|
digest |
Next.js error digest (hash of the error message) |
message |
First 2000 chars |
stack |
First 8000 chars |
page_url |
window.location.href |
browser_info |
User agent, language, viewport |
What's NOT captured
- User identity (the report is anonymous —
org_idanduser_idare null). This is intentional: the endpoint runs without authentication so it can also catch errors on the login page or other public routes. - Form data
- Cookies, localStorage, or any session state
If you want richer attribution (which user, which org), wire Sentry — see Operations roadmap.
Tuning
To find auto-report code:
app/global-error.tsx— UI + the POSTapp/api/auto-error-report/route.ts— server-side insert + dedupe
Both are short and easy to extend if you want to capture additional context or change the recovery UI.