Skip to content

Brisket Error Catalogue

Brisket surfaces errors in three layers:

  1. Next.js framework — RSC render, route-handler exceptions, middleware redirects.
  2. tRPC — typed errors with code, message, and a data.zodError field for input validation failures.
  3. Upstream — Connect/gRPC errors from sirloin (code numeric), 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

#SourceCode / SymptomTriggerUser-VisibleMitigation
1tRPCUNAUTHORIZEDClerk 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.
2tRPCBAD_REQUEST with data.zodErrorZod input validation failure (e.g. malformed character_id).Inline form error using fieldErrors.Client should pre-validate; check schema in router.
3tRPCINTERNAL_SERVER_ERRORUncaught throw in a procedure (sirloin offline, Strapi 5xx, etc.).Generic toast; Sentry captures.Inspect Sentry trace + trpc.${type}.${path} span in Axiom.
4sirloin Connectcode: 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.
5sirloin Connectcode: 4 (DeadlineExceeded)gRPC > 120 s (default defaultTimeoutMs in sirloin-api.ts).Toast: “Something went wrong, please try again.”Retry; investigate sirloin latency.
6sirloin Connectcode: 14 (Unavailable)sirloin pod restart / network blip.Toast.Transport refresh runs every 30 min; manual retry usually clears it.
7Cloudflare TurnstileError("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.
8SubscriptionError("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.
9Clerk webhook400 Invalid signatureSvix HMAC verification failed in /api/webhook/clerk.Webhook source sees retries.Verify CLERK_WEBHOOK_SECRET parity between Clerk dashboard and deploy.
10StrapiError("Failed to load FAQ section (${status})")Non-2xx from Strapi in faq.getCheckoutFaqSection.Checkout FAQ accordion empty.Check Strapi uptime and STRAPI_TOKEN.
11StrapiZod parse failure on FAQ schemaStrapi returned an unexpected shape.Same as #10.Sync schema with chuck content model.
12IntercomSoft-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.
13Next.js middlewareRedirect to /sign-in?redirect_url=...Hitting a non-public route while logged out.Page navigation to sign-in.Expected.
14Next.js middleware404 on /auth-content/*Logged-out request to private asset.404.Expected — gates private media.
15Next.js middlewareRedirect to /exploreLogged-in user hits /sign-in or /sign-up; or invalid redirect_url query.Page navigation to /explore.validateRedirectUrl defends against open-redirect.
16Next.jsRSC Error: Cannot read properties of undefinedFrequently a stale Turbopack chunk after dependency change.Full-page error boundary.pnpm --filter brisket build fresh; clear .next/.
17Next.jsdigest errors in productionSentry-captured uncaught render error with hashed digest.Generic “Something went wrong”.Search digest in Sentry for the source error.
18Sentry / OTelFailed to export traces/logsBad BRISKET_OTEL_* headers (Axiom 401).None visible to user; observability gap.Re-issue Axiom token; redeploy.
19Vitest (CI)Timeout / flake on pnpm testNetwork or fake-timer regression.CI red.Re-run; pin offending test.
20BuildInvalid environment variables: ... (Zod)Required server/client var missing.Build fails.Compare with brisket-env; fill secrets.
21BuildModule not found after pnpm overrides changeReact 19 / pkg override mismatch.Build fails.pnpm install after pulling; nuke .next/ and node_modules/.
22BrowserChargebee.js script load failureNEXT_PUBLIC_CHARGE_BEE_SITE or publishable key wrong / network blocked.Checkout cannot mount.Check site slug; corporate proxies sometimes block *.chargebee.com.
23BrowserClerk publishable key mismatchStage env points at different Clerk instance than backend CLERK_SECRET_KEY.Sign-in loops.Pair publishable+secret per stage.
24BrowserPostHog blocked by ad-blockersposthog.capture no-ops.None visible; analytics gap.Expected; do not error.
25SubscriptionreactivateSubscription 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 name trpc.${type}.${path} (set in tracingMiddleware).
  • Sentry@sentry/nextjs integration captures both server and client errors. Errors have digest mapped 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 in apps/brisket/src/server/api/tests/.