#347·open-seo

Docker self-host: AUTH_MODE=local_noauth crashes client with React error #321 (repeated 404 on /api/auth/get-session)

Author: maciek1992Created Sep 18, 2026Updated Sep 18, 2026

Summary

Following docs/SELF_HOSTING_DOCKER.md exactly, the app boots fine (preflight passes, /api/health returns 200, migrations apply cleanly) but the client crashes in the browser with a full-page error boundary:

Minified React error #321; visit https://react.dev/errors/321 for the full message

Reproduced on both ghcr.io/every-app/open-seo:latest and the pinned release ghcr.io/every-app/open-seo:v0.1.9 — same crash, same asset hash (index-*.js), so it's not tag-specific.

Environment

  • Docker Compose self-hosting (per docs/SELF_HOSTING_DOCKER.md), behind Caddy reverse proxy with HTTP Basic Auth in front (as the docs recommend for local_noauth).
  • .env:
    • AUTH_MODE=local_noauth
    • ALLOWED_HOST=<my-domain>
    • PORT=3001
    • GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / BETTER_AUTH_SECRET set (for optional Search Console integration, per docs/SELF_HOSTING_GOOGLE_SEARCH_CONSOLE.md)
    • DATAFORSEO_API_KEY intentionally left empty for this test (preflight correctly warns but doesn't block boot)
  • docker exec <container> printenv AUTH_MODE confirms local_noauth reaches the running process.
  • Preflight output on boot is clean:
    [ ok ] AUTH_MODE: local_noauth — no auth, single admin user. Do not expose publicly without your own auth in front.
    [warn] DATAFORSEO_API_KEY: Not set — ...
    [ ok ] Search Console: Configured
    [ ok ] ALLOWED_HOST: Requests allowed for host <my-domain>

Observed behavior

  • Server-side logs are completely clean — no errors, no stack traces. Just repeated:
    GET /api/auth/get-session 404 Not Found (7ms)
    (fired 2-4 times per page load)
  • Client console shows the React #321 crash immediately, full-page error boundary ("Try Again" / "Go Back").
  • docker logs shows the client+server build completing successfully on container start (fresh build each time, fingerprint-based cache correctly invalidated when AUTH_MODE changes — confirmed by watching docker-entrypoint.sh's "Building client + server (first start...)" log line).

Hypothesis

src/client/features/auth/useHostedAuthRouteGuard.ts unconditionally calls useSession() (better-auth client) regardless of AUTH_MODE, which hits /api/auth/get-session. In local_noauth mode the server apparently doesn't mount the better-auth routes (hence the 404s), and something about how the resulting error/pending state is handled seems to crash the render tree with "Invalid hook call" (React error #321).

I did not confirm this is a build-time vs runtime AUTH_MODE mismatch (import.meta.env.AUTH_MODE in src/lib/auth-mode.ts for the client vs env.AUTH_MODE from cloudflare:workers in src/lib/auth.ts for the server) — docker-entrypoint.sh does rebuild fresh with the right env each time in my testing, so that specific issue from #190 doesn't seem to be the direct cause here, but the underlying local_noauth-vs-hosted route mismatch feels related.

Repro steps

  1. Follow docs/SELF_HOSTING_DOCKER.md with AUTH_MODE=local_noauth, any ALLOWED_HOST matching your reverse-proxy origin.
  2. docker compose up -d, wait for healthy.
  3. Open the app in a browser (any browser, tested in a headless Chromium via an automation tool, and manually).
  4. Full-page crash with "Minified React error #321".

What would help

A minimal repro on a stock docker compose up with no reverse proxy (just localhost) would help rule out anything Caddy/Basic-Auth related on my end, but the clean server-side logs and the specific /api/auth/get-session 404 loop point at the client bundle rather than my proxy setup.

Happy to share more logs/HAR if useful.