Skip to content

fix(backend): Resolve Better Auth user ID / legacy UUID mismatch#135

Merged
enko merged 2 commits intomainfrom
fix/auth-user-id-uuid-mismatch
Mar 15, 2026
Merged

fix(backend): Resolve Better Auth user ID / legacy UUID mismatch#135
enko merged 2 commits intomainfrom
fix/auth-user-id-uuid-mismatch

Conversation

@enko
Copy link
Copy Markdown
Member

@enko enko commented Mar 15, 2026

Summary

  • Auth middleware was passing Better Auth's opaque string ID (session.user.id) as userExternalId to domain queries that join via auth.users.external_id (UUID-typed), causing invalid input syntax for type uuid errors for new user registrations
  • Fix resolves the legacy auth.users.external_id by email in the auth middleware and exposes both userId (legacy UUID) and betterAuthId (opaque string) so each query type gets the correct ID
  • Updated call sites for self-profile/preferences queries to use betterAuthId, all domain queries (friends, encounters, circles, etc.) continue using userId which is now the correct UUID

Test plan

  • Auth middleware unit tests updated and passing (9 tests including new "legacy user not found" case)
  • Backend type-check passes
  • All pre-push checks pass (lint, type-check, build, unit + integration tests)
  • Manual: Register new user → complete onboarding → verify no UUID errors
  • Manual: Existing user login → verify friends/encounters/circles still load

🤖 Generated with Claude Code

The auth middleware was setting userId to Better Auth's opaque string
(session.user.id), but domain queries (friends, encounters, circles,
etc.) join via auth.users.external_id which is UUID-typed, causing
"invalid input syntax for type uuid" errors for new registrations.

Fix: resolve the legacy auth.users.external_id in the auth middleware
and expose both IDs — userId (legacy UUID) for domain queries and
betterAuthId (opaque string) for auth."user" queries (self-profile,
preferences).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
const db = c.get('db');
const [legacyUser] = await getLegacyExternalIdByEmail.run({ email: session.user.email }, db);

if (!legacyUser) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Performance: Extra DB Round-Trip on Every Authenticated Request

getLegacyExternalIdByEmail is called inside authMiddleware, which runs on every protected route. This adds a synchronous DB lookup to every single authenticated request.

Two mitigations to consider:

  1. Add an index on auth.users(email) if one doesn't exist — keeps the query fast even at scale.
  2. Longer-term: Consider caching the email → external_id mapping in the session context or resolving it at registration time (e.g. store the legacy external_id directly on the Better Auth user record), so the per-request overhead disappears entirely.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed both items:

  1. Index: auth.users(email) already has a UNIQUE constraint and an explicit index (idx_users_email) from the initial schema migration — no additional indexing needed.
  2. as any cast: Replaced with {} as unknown as pg.Pool in b1130c5.

Agree on the longer-term approach of resolving the legacy UUID at registration time to eliminate the per-request lookup.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 15, 2026

## Automated Code Review | Commit | c3fab3c | | Reviewed | 2026-03-15 | | Status | Approved | Critical: 0, Important: 0, Suggestion: 0. All previous issues addressed. Performance: idx_users_email confirmed. Type safety: as-any fixed. Dual-ID split consistently applied. CI: https://github.com/datenknoten/freundebuch/actions/runs/23118484680

Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Found 1 important issue to consider (extra DB round-trip per request). See inline comments.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new issues found. All previous review items resolved (idx_users_email index confirmed; as-any cast fixed). The dual-ID approach is sound and consistently applied. CI: https://github.com/datenknoten/freundebuch/actions/runs/23118484680

@enko enko merged commit af5088b into main Mar 15, 2026
7 checks passed
@github-actions
Copy link
Copy Markdown

🎉 This PR is included in version 2.67.2 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant