[BUG] databaseHooks.user.create.after not firing for Google OAuth signup #1960

Closed
opened 2026-03-13 09:16:37 -05:00 by GiteaMirror · 2 comments
Owner

Originally created by @Maxime-RiseVerse on GitHub (Sep 18, 2025).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

  1. Configure Better Auth with databaseHooks.user.create.after to create a default organization.
  2. Sign up a new user via email/password.
    • Hook fires correctly → logs appear → organization created.
  3. Sign up a new user via Google OAuth (new Google account / fresh email).
    • Hook does not fire → no logs → no organization created.

Current vs. Expected behavior

Current behavior:

  • Email signup → user.create.after fires → organization created.
  • Google OAuth signup → user.create.after does not fire → nothing happens.

Expected behavior:

  • databaseHooks.user.create.after should fire consistently for ALL user creation methods
    (both email/password and OAuth), as documented.

What version of Better Auth are you using?

1.3.11

System info

{
  "system": {
    "platform": "win32",
    "arch": "x64",
    "version": "Windows 11 Pro",
    "release": "10.0.26100",
    "cpuCount": 16,
    "cpuModel": "Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz",
    "totalMemory": "31.88 GB",
    "freeMemory": "20.62 GB"
  },
  "node": {
    "version": "v22.14.0",
    "env": "development"
  },
  "packageManager": {
    "name": "npm",
    "version": "10.9.2"
  },
  "frameworks": [
    {
      "name": "next",
      "version": "15.5.3"
    },
    {
      "name": "react",
      "version": "19.1.1"
    }
  ],
  "databases": [
    {
      "name": "pg",
      "version": "^8.16.3"
    },
    {
      "name": "drizzle",
      "version": "^0.44.5"
    }
  ],
  "betterAuth": {
    "version": "^1.3.11",
    "config": null
  }
}

Which area(s) are affected? (Select all that apply)

Backend

Auth config (if applicable)

databaseHooks: {
  user: {
    create: {
      after: async (userData) => {
        console.log("User created:", userData.id);
        // Create default organization
        try {
          const orgId = `org_${Date.now()}`;
          // ... organization creation code
        } catch {}
      }
    }
  }
},
socialProviders: {
  google: {
    clientId: process.env.GOOGLE_CLIENT_ID,
    clientSecret: process.env.GOOGLE_CLIENT_SECRET
  }
}

Additional context

No response

Originally created by @Maxime-RiseVerse on GitHub (Sep 18, 2025). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce 1. Configure Better Auth with `databaseHooks.user.create.after` to create a default organization. 2. Sign up a new user via **email/password**. - ✅ Hook fires correctly → logs appear → organization created. 3. Sign up a new user via **Google OAuth** (new Google account / fresh email). - ❌ Hook does not fire → no logs → no organization created. ### Current vs. Expected behavior Current behavior: - Email signup → `user.create.after` fires → organization created. - Google OAuth signup → `user.create.after` does not fire → nothing happens. Expected behavior: - `databaseHooks.user.create.after` should fire consistently for ALL user creation methods (both email/password and OAuth), as documented. ### What version of Better Auth are you using? 1.3.11 ### System info ```bash { "system": { "platform": "win32", "arch": "x64", "version": "Windows 11 Pro", "release": "10.0.26100", "cpuCount": 16, "cpuModel": "Intel(R) Core(TM) i7-10700K CPU @ 3.80GHz", "totalMemory": "31.88 GB", "freeMemory": "20.62 GB" }, "node": { "version": "v22.14.0", "env": "development" }, "packageManager": { "name": "npm", "version": "10.9.2" }, "frameworks": [ { "name": "next", "version": "15.5.3" }, { "name": "react", "version": "19.1.1" } ], "databases": [ { "name": "pg", "version": "^8.16.3" }, { "name": "drizzle", "version": "^0.44.5" } ], "betterAuth": { "version": "^1.3.11", "config": null } } ``` ### Which area(s) are affected? (Select all that apply) Backend ### Auth config (if applicable) ```typescript databaseHooks: { user: { create: { after: async (userData) => { console.log("User created:", userData.id); // Create default organization try { const orgId = `org_${Date.now()}`; // ... organization creation code } catch {} } } } }, socialProviders: { google: { clientId: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET } } ``` ### Additional context _No response_
GiteaMirror added the bug label 2026-03-13 09:16:37 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Sep 18, 2025):

The databaseHooks.user.create.after hook is designed to fire for all user creation methods, including Google OAuth, in Better Auth v1.3.11. Both email/password and OAuth signups use the same internal logic for hook execution, so there’s no intentional difference in the codebase that would skip the hook for OAuth signups. If the hook isn’t firing for Google OAuth, it’s likely due to a runtime error, silent failure in your hook handler, or a configuration issue—not a bug in Better Auth itself.

One important detail: since v1.3.10, the user creation transaction isn’t committed until after all hooks finish, which means the new user isn’t visible to internal queries (like findUserById) during the hook execution. If your organization creation logic relies on querying the just-created user, it may fail or return null in the hook context. To work around this, defer organization creation until after the transaction commits, move the logic outside the hook, or use a custom event that fires post-commit. More details are discussed here.

For troubleshooting, add error logging to your hook and check for exceptions. If you need to create related records (like organizations) after user creation, consider deferring that logic until the user is fully committed to the database.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

@dosubot[bot] commented on GitHub (Sep 18, 2025): <!-- Answer --> The `databaseHooks.user.create.after` hook is designed to fire for all user creation methods, including Google OAuth, in Better Auth v1.3.11. Both email/password and OAuth signups use the same internal logic for hook execution, so there’s no intentional difference in the codebase that would skip the hook for OAuth signups. If the hook isn’t firing for Google OAuth, it’s likely due to a runtime error, silent failure in your hook handler, or a configuration issue—not a bug in Better Auth itself. One important detail: since v1.3.10, the user creation transaction isn’t committed until after all hooks finish, which means the new user isn’t visible to internal queries (like `findUserById`) during the hook execution. If your organization creation logic relies on querying the just-created user, it may fail or return null in the hook context. To work around this, defer organization creation until after the transaction commits, move the logic outside the hook, or use a custom event that fires post-commit. More details are discussed [here](https://github.com/better-auth/better-auth/issues/4718). For troubleshooting, add error logging to your hook and check for exceptions. If you need to create related records (like organizations) after user creation, consider deferring that logic until the user is fully committed to the database. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/c3c7930d-bd84-4735-915a-4b3bb4f63dd7?feedback_type=other)</sup>&nbsp;&nbsp;[![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/4745)
Author
Owner

@Maxime-RiseVerse commented on GitHub (Sep 18, 2025):

@dosu You're absolutely right - since v1.3.10, the transaction isn't committed until after hooks finish, which explains why auth.api.createOrganization fails inside the hook.

The cleanest solution is to skip database hooks entirely and create the organization on first dashboard access instead:

 // dashboard-shell-wrapper.tsx - runs when user accesses dashboard
 if (userOrganizations.length === 0) {
   await auth.api.createOrganization({
     body: { name, slug },
     headers: await headers(),
   });
 }

This works perfectly because:

  • User is fully committed to DB
  • Session already exists
  • Works for both email & OAuth signups

Thanks for clarifying the transaction timing issue. Closing this as it's expected behavior, not a bug.

@Maxime-RiseVerse commented on GitHub (Sep 18, 2025): @dosu You're absolutely right - since v1.3.10, the transaction isn't committed until after hooks finish, which explains why `auth.api.createOrganization` fails inside the hook. The cleanest solution is to skip database hooks entirely and create the organization on first dashboard access instead: ```typescript // dashboard-shell-wrapper.tsx - runs when user accesses dashboard if (userOrganizations.length === 0) { await auth.api.createOrganization({ body: { name, slug }, headers: await headers(), }); } ``` This works perfectly because: - User is fully committed to DB - Session already exists - Works for both email & OAuth signups Thanks for clarifying the transaction timing issue. Closing this as it's expected behavior, not a bug.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#1960