nextauthjs/next-auth · error

Error creating user: Cannot get user after creation.

Error message

Error creating user: Cannot get user after creation.

What it means

The D1 adapter inserts a new user with a batch that includes a follow-up SELECT by id, and throws this if the returned user is still undefined. It means the INSERT and/or the immediate re-fetch did not yield a row, so the adapter refuses to return a bogus result. This is an internal consistency failure rather than a validation error you can usually fix at the call site.

Source

Thrown at packages/adapter-d1/src/index.ts:179

      const id: string = crypto.randomUUID()
      const createBindings = [
        id,
        user.name,
        user.email,
        user.emailVerified?.toISOString(),
        user.image,
      ]
      const getBindings = [id]

      const newUser = await createRecord<AdapterUser>(
        db,
        CREATE_USER_SQL,
        createBindings,
        GET_USER_BY_ID_SQL,
        getBindings
      )
      if (newUser) return newUser
      throw new Error("Error creating user: Cannot get user after creation.")
    },
    async getUser(id) {
      return await getRecord<AdapterUser>(db, GET_USER_BY_ID_SQL, [id])
    },
    async getUserByEmail(email) {
      return await getRecord<AdapterUser>(db, GET_USER_BY_EMAIL_SQL, [email])
    },
    async getUserByAccount({ providerAccountId, provider }) {
      return await getRecord<AdapterUser>(db, GET_USER_BY_ACCOUNTL_SQL, [
        providerAccountId,
        provider,
      ])
    },
    async updateUser(user) {
      const params = await getRecord<AdapterUser>(db, GET_USER_BY_ID_SQL, [
        user.id,
      ])
      if (params) {

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Verify the users table exists with the schema from packages/adapter-d1 (run the provided migration SQL) and that id is the primary key.
  2. Check the D1 binding name in wrangler.toml / the binding passed to D1Adapter(db) actually points at your database.
  3. Ensure you are not overriding the users table name/columns in a way that breaks GET_USER_BY_ID_SQL.
  4. Upgrade the adapter; older versions had batch execution issues on some D1/miniflare builds.

Example fix

// before
const user = await adapter.createUser({ id: undefined, email, emailVerified: null })
// after
const user = await adapter.createUser({
  id: crypto.randomUUID(),
  email,
  emailVerified: null,
})
if (!user) throw new Error('user creation failed — check D1 schema/binding')
Defensive patterns

Strategy: try-catch

Validate before calling

const existing = await adapter.getUser(id)
if (existing) throw new Error(`User ${id} already exists`)

Type guard

function isAdapterUser(u: unknown): u is AdapterUser {
  return !!u && typeof u === 'object' && typeof (u as AdapterUser).id === 'string'
}

Try / catch

try {
  const user = await adapter.createUser(userData)
} catch (e) {
  if (e instanceof Error && e.message.includes('Cannot get user after creation')) {
    // inspect D1 binding/table schema, possibly retry getUser or surface config error
  }
  throw e
}

Prevention

When it happens

Trigger: adapter.createUser() when the INSERT silently fails or the follow-up GET_USER_BY_ID_SQL returns no row (e.g. mismatched id column/binding, batch statement ordering issue, or the users table lacking the row after insert due to constraints swallowed by D1).

Common situations: Wrong table schema (users table not created via the adapter's SQL migrations), D1 binding misconfigured so writes go nowhere, custom schema overrides changing column names so the SELECT misses, or running on miniflare/local D1 with batch quirks.

Related errors


AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28). Data as JSON: /api/errors/b1d192a7dcca6c57. Report an issue: GitHub.