Brisket Error Catalogue
Brisket surfaces errors in three layers:
- Next.js framework — RSC render, route-handler exceptions, middleware redirects.
- tRPC — typed errors with
code,message, and adata.zodErrorfield for input validation failures. - Upstream — Connect/gRPC errors from sirloin (
codenumeric), Strapi/Intercom HTTP errors, Clerk webhook signature failures.
tRPC Error Shape
All tRPC procedure failures serialize through the errorFormatter in apps/brisket/src/server/api/trpc.ts:
{ "shape": { "message": "string", "code": -32603, // JSON-RPC code mapped from TRPCError code "data": { "code": "BAD_REQUEST", // TRPCError code string "httpStatus": 400, "path": "subscription.createPrimerCheckout", "stack": "...", // dev only "zodError": { // present when input validation fails "formErrors": [], "fieldErrors": { "itemPriceId": ["Required"] } } } }}Clients should branch on error.data.code (string), not the JSON-RPC numeric code.
Top Errors
| # | Source | Code / Symptom | Trigger | User-Visible | Mitigation |
|---|---|---|---|---|---|
| 1 | tRPC | UNAUTHORIZED | Clerk session missing/expired on a protectedProcedure. | Auto-redirect to /sign-in via middleware; mid-flight tRPC calls surface as a toast. | Re-auth. Verify CLERK_SECRET_KEY and clock skew. |
| 2 | tRPC | BAD_REQUEST with data.zodError | Zod input validation failure (e.g. malformed character_id). | Inline form error using fieldErrors. | Client should pre-validate; check schema in router. |
| 3 | tRPC | INTERNAL_SERVER_ERROR | Uncaught throw in a procedure (sirloin offline, Strapi 5xx, etc.). | Generic toast; Sentry captures. | Inspect Sentry trace + trpc.${type}.${path} span in Axiom. |
| 4 | sirloin Connect | code: 5 (NotFound) | Subscription / character missing. Subscription router rethrows as Error("No subscription found for user"). | Empty state UI / billing onboarding redirect. | Expected for new users. |
| 5 | sirloin Connect | code: 4 (DeadlineExceeded) | gRPC > 120 s (default defaultTimeoutMs in sirloin-api.ts). | Toast: “Something went wrong, please try again.” | Retry; investigate sirloin latency. |
| 6 | sirloin Connect | code: 14 (Unavailable) | sirloin pod restart / network blip. | Toast. | Transport refresh runs every 30 min; manual retry usually clears it. |
| 7 | Cloudflare Turnstile | Error("Security check failed. Please try again.") | subscription.createPrimerCheckout token verification failed (verifyCfTurnstileToken). | Modal asks to re-prove. | Re-issue widget; check CF_TURNSTILE_SECRET_KEY. |
| 8 | Subscription | Error("This plan is not available for your account.") | NSFW plan selected without nsfw-onboarding PostHog flag. | Plan-selector error banner. | Verify flag rollout in PostHog. |
| 9 | Clerk webhook | 400 Invalid signature | Svix HMAC verification failed in /api/webhook/clerk. | Webhook source sees retries. | Verify CLERK_WEBHOOK_SECRET parity between Clerk dashboard and deploy. |
| 10 | Strapi | Error("Failed to load FAQ section (${status})") | Non-2xx from Strapi in faq.getCheckoutFaqSection. | Checkout FAQ accordion empty. | Check Strapi uptime and STRAPI_TOKEN. |
| 11 | Strapi | Zod parse failure on FAQ schema | Strapi returned an unexpected shape. | Same as #10. | Sync schema with chuck content model. |
| 12 | Intercom | Soft-fail (logger.warn) | Missing token, missing email, or contact not found. | No user-visible error — support widget silently no-ops. | Verify INTERCOM_API_TOKEN; ensure user has primary email. |
| 13 | Next.js middleware | Redirect to /sign-in?redirect_url=... | Hitting a non-public route while logged out. | Page navigation to sign-in. | Expected. |
| 14 | Next.js middleware | 404 on /auth-content/* | Logged-out request to private asset. | 404. | Expected — gates private media. |
| 15 | Next.js middleware | Redirect to /explore | Logged-in user hits /sign-in or /sign-up; or invalid redirect_url query. | Page navigation to /explore. | validateRedirectUrl defends against open-redirect. |
| 16 | Next.js | RSC Error: Cannot read properties of undefined | Frequently a stale Turbopack chunk after dependency change. | Full-page error boundary. | pnpm --filter brisket build fresh; clear .next/. |
| 17 | Next.js | digest errors in production | Sentry-captured uncaught render error with hashed digest. | Generic “Something went wrong”. | Search digest in Sentry for the source error. |
| 18 | Sentry / OTel | Failed to export traces/logs | Bad BRISKET_OTEL_* headers (Axiom 401). | None visible to user; observability gap. | Re-issue Axiom token; redeploy. |
| 19 | Vitest (CI) | Timeout / flake on pnpm test | Network or fake-timer regression. | CI red. | Re-run; pin offending test. |
| 20 | Build | Invalid environment variables: ... (Zod) | Required server/client var missing. | Build fails. | Compare with brisket-env; fill secrets. |
| 21 | Build | Module not found after pnpm overrides change | React 19 / pkg override mismatch. | Build fails. | pnpm install after pulling; nuke .next/ and node_modules/. |
| 22 | Browser | Chargebee.js script load failure | NEXT_PUBLIC_CHARGE_BEE_SITE or publishable key wrong / network blocked. | Checkout cannot mount. | Check site slug; corporate proxies sometimes block *.chargebee.com. |
| 23 | Browser | Clerk publishable key mismatch | Stage env points at different Clerk instance than backend CLERK_SECRET_KEY. | Sign-in loops. | Pair publishable+secret per stage. |
| 24 | Browser | PostHog blocked by ad-blockers | posthog.capture no-ops. | None visible; analytics gap. | Expected; do not error. |
| 25 | Subscription | reactivateSubscription rejection (logged) | Sirloin rejects reactivation during downgrade detection in createPrimerCheckout. | Checkout still proceeds; non-fatal. | Inspect logs for Error reactivating subscription. |
Where to Look
- tRPC traces — Axiom dataset
beef-staging/beef-prod, span nametrpc.${type}.${path}(set intracingMiddleware). - Sentry —
@sentry/nextjsintegration captures both server and client errors. Errors havedigestmapped to source. - PostHog — only tracks lifecycle events from
app/api/webhook/clerk/route.ts(account_created,logged_in).
Anchors
- Error-handling standards:
standards/security-model,standards/auth-model. - Observability:
operations/observability. - Testing:
operations/testing-strategy— Vitest inapps/brisket/src/server/api/tests/.