Skip to main content
← Back to list
01Issue
BugOpenSwamp ClubPublic
AssigneesNone

Relationships

#1811 Invite failures emit no telemetry, so a rejected invitation leaves no trace anywhere

Opened by keeb · 8/24/2026

Found by code scan of the collective invite route.

The defect

routes/api/v1/collectives/[slug]/invite.ts:114 tracks the happy path only — a single track("collective_invite_sent", ...) call, passing the session user id and the slug.

That call sits after the success branch. Every rejection returns a JSON error and vanishes:

  • Unauthorized (401, line 40)
  • Invalid request body (400, line 47)
  • Username or email is required (400, line 54)
  • Operative not found (400, line 69)
  • Not found (404, line 87) when the slug does not resolve
  • anything thrown out of inviteMember (400, line 103) — which covers the canInvite rejection, the already-a-member guard, and every Better Auth createInvitation throw

None of these are counted, sampled, or logged as an event. The only durable artifact of a failed invite is the absence of a row in the invitation collection, which is indistinguishable from an invite that was never attempted.

Why this matters more than a usual missing metric

Inviting a collaborator is the first collaborative act in the product and the trigger for the trial. When it fails, the operative sees a red string in a form and nothing else happens — no email, no row, no event. From the outside there is no way to answer "did anyone try to invite someone today and get turned away," let alone "what did the server tell them." Diagnosing a single reported failure means reconstructing it from session-row write timestamps, because that is the only side effect a partially-completed invite leaves behind.

The taxonomy is small and already enumerated in the code, so the event is cheap.

Suggested fix

Emit collective_invite_failed on every non-2xx return from this route, carrying:

  • reason — a stable slug per branch (unauthorized, invalid-body, missing-identifier, operative-not-found, collective-not-found, role-not-allowed, already-member, provider-error)
  • slug, inviter_username, and whether the submitted identifier was an email or a username (not the identifier itself)

Two things fall out of that immediately: which rejection dominates, and whether the operative-not-found rate tracks the typeahead gap in #1809.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED

Open

8/24/2026, 11:57:17 PM

No activity in this phase yet.

03Sludge Pulse

Sign in to post a ripple.