Skip to content

Fennec Errors & User-Visible Failures

Fennec is a thin SPA — most “fennec errors” are upstream failures from brain or the embedded Strapi backend, surfaced via TanStack Query error states. This page enumerates the failures an operator is likely to see in the UI and what to do about them.

Errors fall into five buckets:

  1. Auth — Clerk session, role gating, JWT issues
  2. Network — CORS, DNS, upstream unavailable
  3. Validation — 4xx from upstream, malformed payloads
  4. Build / runtime config — missing env vars, prefix mistakes
  5. Generations Dashboard — Media ID lookup results
# What the user sees Likely cause First action
1 Stuck on “Loading…” indefinitely after login useCurrentUserQuery failing silently — brain returns 401 but Clerk session loaded Check browser console for /users/me 401; verify REACT_APP_BRAIN_URL and that Clerk JWT is being sent
2 Redirected back to /profile from a guarded route PrivateRoute saw isError or insufficient role from /users/me (PrivateRoute.tsx) Confirm the user’s role in brain DB; check useCurrentUserRole output in React DevTools
3 Redirected to /login immediately on every page load Clerk session expired or not initialised; window.Clerk undefined Force sign-out, clear cookies for the Clerk frontend domain, sign back in
4 “401 Unauthorized” toast on a brain mutation JWT expired mid-session; getClerkToken returned empty Reload page (Clerk refresh) or sign out/in. If persistent, see fennec-runbook.md Clerk section
5 Login page renders but Clerk widget never mounts (blank panel) REACT_APP_CLERK_PUBLISHABLE_KEY missing or wrong-environment key Verify env value matches the Clerk instance for this deploy (dev vs prod)
6 “Forbidden” / 403 on admin pages for an existing admin Role drift between Clerk metadata and brain users table Cross-check GET /users/me response; reconcile in brain
# What the user sees Likely cause First action
7 “Network Error” or ERR_NETWORK on every brain call REACT_APP_BRAIN_URL wrong, brain down, or DNS failure curl $REACT_APP_BRAIN_URL/health; check Railway brain deploy status
8 CORS preflight failure (“blocked by CORS policy”) Brain or Strapi CORS allowlist missing the fennec origin Update upstream CORS config; brain config in apps/brain/src/config/
9 “Cookies not sent” symptom: works locally, fails in deployed env withCredentials: true requires Access-Control-Allow-Credentials: true and explicit origin Confirm upstream is not using a * Access-Control-Allow-Origin; explicit origin required
10 Spinner forever on a list page (e.g. Generations Dashboard) Upstream timeout; TanStack Query retrying silently DevTools → Network tab → look for hanging requests; check brain logs
11 “502 / 503 Bad Gateway” toast or red page Upstream rolling deploy or crashed Check Railway deploy events for the affected upstream
# What the user sees Likely cause First action
12 “400 Bad Request” on a save Form payload mismatch with upstream DTO; mapper drift Inspect request body in DevTools; compare with brain DTO definition
13 “404 Not Found” on a known resource ID typo, soft-deleted record, or env points at the wrong DB Confirm REACT_APP_BACKEND_URL / REACT_APP_BRAIN_URL match expected environment
14 “409 Conflict” creating a preset / prompt Duplicate name; unique constraint Rename and retry
15 “413 Payload Too Large” uploading media Upstream body limit hit before R2; image not routed via pre-signed URL Use the pre-signed-URL flow (brainInputMedia.ts) for large files
16 “415 Unsupported Media Type” Browser failed to set multipart boundary, or Content-Type overridden by caller Pass raw FormData to apiClient — it intentionally omits Content-Type for FormData
17 “422 Unprocessable Entity” with no clear field error Strapi validation; missing relation Inspect Strapi response body — Strapi nests errors under error.details
# What the user sees Likely cause First action
18 “undefined/users/me” appears as request URL in Network tab apiConfig.brain is undefined — REACT_APP_BRAIN_URL not baked into bundle Set the variable and rebuild (Vite inlines env at build time, not runtime)
19 New env var added but value is undefined in app Missing REACT_APP_ prefix (see fennec-env.md) Rename variable; rebuild
20 Image URLs broken on prod, fine in dev VITE_IMAGES_CDN_URL read in lib/utils.ts:9 ignored due to envPrefix: "REACT_APP_" Switch the read to REACT_APP_IMAGES_CDN_URL (or drop the override), set in Railway, redeploy. TODO(@law): pick rename vs remove.
21 “Maximum update depth exceeded” on a page using Semantic UI form Legacy Semantic UI React component re-rendering in StrictMode-equivalent path Migrate component to shadcn/Base UI per apps/fennec/AGENTS.md guidance
22 Blank page after deploy, console shows MIME-type or 404 on /assets/* CDN cache pinned to old index.html referencing dropped chunk hashes Flush CDN per fennec-runbook.md; re-rollout

The Media ID filter reads one row from Brain; these rows separate “not in Brain” from “lookup failed”.

# What the user sees Likely cause First action
23 Generations Dashboard Media ID filter shows “No generations found” for a known media Brain has no Generation row for it — the filter reads only Brain genId. Causes: not dispatched yet; failed at dispatch on a permanent input error or Brain 4xx (sendmediageneration.go); or failed once its generation window expired (checkmediageneration.go) Check the media status in Sirloin: FAILED means one of the failure paths; PENDING means queued — the dispatch worker retries it and it has no deadline; GENERATING (claimed before the Brain call, storage/media.go) expires after the generation window (10 min image, 45 min video, checkmediageneration.go)
24 Generations Dashboard shows “Could not look up this media ID. Try again.” Brain detail lookup failed with a non-404 (5xx, timeout, 401) after retries DevTools → Network → GET /generation/dashboard/:id status; then row 4 (401) or row 11 (5xx)
flowchart TD
    A[User reports error] --> B{Auth-related?}
    B -- yes --> C[Check Clerk session + /users/me + role]
    B -- no --> D{Network tab shows 4xx?}
    D -- 401/403 --> C
    D -- 4xx other --> E[Validation: inspect payload + upstream DTO]
    D -- 5xx --> F[Upstream incident: check Railway / brain logs]
    D -- no request --> G[CORS or DNS — check console]
    G --> H{undefined in URL?}
    H -- yes --> I[Env var missing; rebuild required]
    H -- no --> F