Summary
In authenticated mode, the sign-in page enters an infinite client-side redirect loop and never renders the login form, so no one can log into the web UI. The next query param keeps nesting on each redirect until the URL grows to thousands of characters and requests start returning HTTP 414 URI Too Long.
Environment
- Self-hosted Docker,
ghcr.io/paperclipinc/paperclip, single replica, external Postgres (also reproduced with embedded Postgres).
deploymentMode: authenticated, exposure: private, auth.baseUrlMode: explicit with a publicBaseUrl, behind an HTTPS reverse proxy.
- Reproduced on a clean browser profile (no cookies/localStorage) with headless Chromium (Playwright) — so it is not stale client state.
Affected vs working builds
Same DB, same env/config — only the image changes the behavior:
- ✅ Works (form renders, lands on
/auth?next=/): image revision b57c11d7.
- ❌ Broken: revision
e02ab855 and every later build incl. current :latest (e.g. 729c2f7f).
Steps to reproduce
- Deploy in
authenticated + private mode behind an HTTPS reverse proxy.
- Open the base URL in a fresh browser (no session).
- Redirected to
/auth/sign-in?next=%2F, which then redirects to /auth/sign-in?next=<url-encoded previous> recursively, forever.
Observed
- Anonymous requests during the loop:
GET /api/auth/get-session → 401, GET /api/companies → 403 (Board access required), GET /api/adapters → 403. The SPA reacts by redirecting to sign-in instead of rendering the form.
- The sign-in route appears to apply the "redirect unauthenticated → sign-in?next=current" guard to itself, so
next nests indefinitely; eventually the server returns HTTP 414.
- Page body stays near-empty; no
input[type=password] is ever mounted. No uncaught JS exceptions.
- On working revision
b57c11d7 the same flow lands on /auth?next=/ and renders the form (the route path changed from /auth to /auth/sign-in between the working and broken builds — likely where the regression sits).
Expected
/auth/sign-in should render the login form for anonymous users and must not apply the unauthenticated-redirect guard to the sign-in route itself.
Extra
Happy to share the minimal Playwright repro script and the full network trace.
Summary
In
authenticatedmode, the sign-in page enters an infinite client-side redirect loop and never renders the login form, so no one can log into the web UI. Thenextquery param keeps nesting on each redirect until the URL grows to thousands of characters and requests start returning HTTP 414 URI Too Long.Environment
ghcr.io/paperclipinc/paperclip, single replica, external Postgres (also reproduced with embedded Postgres).deploymentMode: authenticated,exposure: private,auth.baseUrlMode: explicitwith apublicBaseUrl, behind an HTTPS reverse proxy.Affected vs working builds
Same DB, same env/config — only the image changes the behavior:
/auth?next=/): image revisionb57c11d7.e02ab855and every later build incl. current:latest(e.g.729c2f7f).Steps to reproduce
authenticated+privatemode behind an HTTPS reverse proxy./auth/sign-in?next=%2F, which then redirects to/auth/sign-in?next=<url-encoded previous>recursively, forever.Observed
GET /api/auth/get-session→ 401,GET /api/companies→ 403 (Board access required),GET /api/adapters→ 403. The SPA reacts by redirecting to sign-in instead of rendering the form.nextnests indefinitely; eventually the server returns HTTP 414.input[type=password]is ever mounted. No uncaught JS exceptions.b57c11d7the same flow lands on/auth?next=/and renders the form (the route path changed from/authto/auth/sign-inbetween the working and broken builds — likely where the regression sits).Expected
/auth/sign-inshould render the login form for anonymous users and must not apply the unauthenticated-redirect guard to the sign-in route itself.Extra
Happy to share the minimal Playwright repro script and the full network trace.