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
Section titled “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
Section titled “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; error telemetry. | Inspect error logs and the 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 |
Uncaught render error with hashed digest. | Generic “Something went wrong”. | Search the digest in Axiom logs and correlate the server error. |
| 18 | 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
Section titled “Where to Look”- tRPC traces — Axiom dataset
beef-staging/beef-prod, span nametrpc.${type}.${path}(set intracingMiddleware). - Axiom error logs: server errors use the existing Pino/OTel path. Browser errors use
/api/telemetry. Search browser reports bydigest,path, andrelease. Browser stacks remain raw; automatic source-map symbolication is not provided. - PostHog — only tracks lifecycle events from
app/api/webhook/clerk/route.ts(account_created,logged_in).
Anchors
Section titled “Anchors”- Error-handling standards:
standards/security-model,standards/auth-model. - Observability:
operations/observability. - Testing:
operations/testing-strategy— Vitest inapps/brisket/src/server/api/tests/.