Skip to main content
← Back to list
01Issue
BugShippedSwamp ClubPublic
Assigneeskeeb

Relationships

#1204 Collective invite emailed-link return path is dropped: /accept-invite sends ?returnUrl= but /login reads ?redirect=

Opened by keeb · 7/17/2026· Shipped 8/14/2026

The collective-invite accept flow loses the return destination for every auth method, so after signing in the invitee lands on /profile instead of back on the accept-invite page.

Root cause

routes/o/[slug]/accept-invite.tsx (line ~50) redirects an unauthenticated invitee to:

/login?returnUrl=<encoded accept-invite url>

but routes/login.tsx (line ~27) only reads the redirect query param:

const rawRedirect = [HOST-1]("redirect");

The param names don't match (returnUrl vs redirect), so the return URL is silently discarded. After login/signup the user is sent to the default /profile and never returns to /o/<slug>/accept-invite, so the InviteAcceptor island is never shown.

Impact

Even setting aside the OAuth-specific failure, the emailed-link path is broken for email/password too. (The server-side auto-claim added for #1186 makes this non-blocking — invites are now claimed on verified sign-in regardless — but the emailed link still doesn't deep-link back correctly, which is confusing UX.)

Fix direction

Align the param name: either have accept-invite.tsx emit ?redirect=, or have login.tsx read returnUrl. Also thread it through the new-user OAuth path (newUserCallbackURL in islands/SignInForm.tsx is hardcoded to /choose-username and drops the destination), and forward it out of /choose-username.

Found while triaging #1186.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 4 MOREPR_MERGED+ 1 MORENOTIFICATION_SKIPPED

Shipped

8/14/2026, 7:44:51 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
keeb assigned keeb8/14/2026, 6:17:49 PM
Editable. Press Enter to edit.

keeb commented 8/12/2026, 3:54:07 PM

Half of this is fixed; recording what remains so the scope is accurate.

Fixed — the param-name mismatch that was the root cause. routes/login.tsx:30 now reads returnUrl first and falls back to redirect:

const rawRedirect = url.searchParams.get("returnUrl") ??
  url.searchParams.get("redirect");

routes/o/[slug]/accept-invite.tsx:54 still emits ?returnUrl=, so the emailed link now deep-links back correctly for email/password and for an existing-account social sign-in.

Still open — the second half this issue named: the new-user OAuth path. newUserCallbackURL in islands/SignInForm.tsx is customised only for the CLI callback (cliCallback), never for redirect. At lines 293, 377, 451 and 523 it is initialised to a bare /choose-username and only rewritten when cliCallback is set:

let callbackURL = redirect ?? "/profile";
let newUserCallbackURL = "/choose-username";   // <- redirect never threaded

So an invitee who clicks the emailed link and signs up with a social provider still lands on /choose-username with the destination dropped, and never returns to the accept-invite page. Four call sites, one per provider.

Staying open, scoped to that.

Sign in to post a ripple.