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

Relationships

#1475 oauth_sign_in telemetry records provider as the literal ":id" for every event

Opened by keeb · 7/29/2026· Shipped 8/2/2026

Every oauth_sign_in telemetry event ever emitted records the provider as the literal string :id instead of google/github/discord/microsoft. The provider dimension on OAuth sign-in is therefore unusable, and has been since the event was introduced.

Cause

lib/auth.ts, in the hooks.after middleware:

} else if (ctx.path.startsWith("/callback/") && newSession) {
  const provider = ctx.path.split("/callback/")[1];

Better Auth registers that endpoint as createAuthEndpoint("/callback/:id", ...) (better-auth/dist/api/routes/callback.mjs), so ctx.path is the unresolved route pattern, not the concrete request path. "/callback/:id".split("/callback/")[1] is ":id", which is truthy, so the guard passes and the bad value is tracked.

The sibling branch for oauth_redirect is correct because it reads ctx.body.provider (a real value supplied by the client) rather than parsing the path.

Evidence (ClickHouse, swamp.events)

event provider count first seen last seen
oauth_redirect google 535 2026-02-27 2026-07-29
oauth_redirect github 393 2026-02-27 2026-07-29
oauth_redirect discord 54 2026-02-27 2026-07-27
oauth_redirect microsoft 25 2026-03-06 2026-07-29
oauth_sign_in :id 791 2026-02-27 2026-07-29

791 of 791 oauth_sign_in events carry :id. Zero carry a real provider.

swamp.events has a materialized column:

oauth_provider LowCardinality(String) MATERIALIZED JSONExtractString(properties, 'oauth_provider')

Nothing writes an oauth_provider property — the code writes provider. That column is populated on 0 of 54,754,417 rows. It is either dead weight or was intended to read provider; worth resolving alongside the fix so the two do not drift again.

Impact

  • No provider breakdown for successful OAuth sign-ins. "Which IdP do operatives actually complete signup with?" is unanswerable from the ledger, even though the funnel's first half (oauth_redirect) has clean provider data. Comparing the two halves to find a provider-specific failure — exactly the analysis that would have surfaced swamp-club#1459 sooner — is impossible.
  • Go-forward only. Historical events cannot be repaired: the provider was never captured, and distinct_id alone does not recover which provider was used.

Suggested fix

Read the resolved param rather than parsing the pattern — ctx.params?.id — and treat a missing or :id-shaped value as unknown instead of tracking it, so a future Better Auth routing change fails loudly rather than silently poisoning the dimension again. A regression test should assert the tracked provider for a concrete callback path; none currently does.

Provenance

Found while tracing michael's session for swamp-club#1459 (the /choose-username SSR 500). Unrelated to that fix and deliberately kept out of it.

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 8 MOREREVIEW+ 3 MOREPR_MERGED+ 1 MORENOTIFICATION_SKIPPED

Shipped

8/2/2026, 7:41:22 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
keeb assigned keeb8/2/2026, 6:32:58 PM

Sign in to post a ripple.