nextauthjs/next-auth · error · AccountNotLinked

The account is already associated with another user

Error message

The account is already associated with another user

What it means

An AccountNotLinked error thrown when the user is already signed in and tries to link a new OAuth account, but that provider account (same provider + providerAccountId) is already linked to a different user in the database. Auth.js refuses to link it to avoid merging accounts, throwing at handle-login.ts:144.

Source

Thrown at packages/core/src/lib/actions/callback/handle-login.ts:144

    return { session, user, isNewUser }
  } else if (account.type === "webauthn") {
    // Check if the account exists
    const userByAccount = await getUserByAccount({
      providerAccountId: account.providerAccountId,
      provider: account.provider,
    })
    if (userByAccount) {
      if (user) {
        // If the user is already signed in with this account, we don't need to do anything
        if (userByAccount.id === user.id) {
          const currentAccount: AdapterAccount = { ...account, userId: user.id }
          return { session, user, isNewUser, account: currentAccount }
        }
        // If the user is currently signed in, but the new account they are signing in
        // with is already associated with another user, then we cannot link them
        // and need to return an error.
        throw new AccountNotLinked(
          "The account is already associated with another user",
          { provider: account.provider }
        )
      }
      // If there is no active session, but the account being signed in with is already
      // associated with a valid user then create session to sign the user in.
      session = useJwtSession
        ? {}
        : await createSession({
            sessionToken: generateSessionToken(),
            userId: userByAccount.id,
            expires: fromDate(options.session.maxAge),
          })

      const currentAccount: AdapterAccount = {
        ...account,
        userId: userByAccount.id,
      }

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Remove the conflicting account row from your adapter's accounts table (or unlink it via your adapter) so it can be linked to the current user.
  2. Sign in with the user that already owns the OAuth account instead of creating a second one.
  3. If email-verified linking is acceptable, set allowDangerousEmailAccountLinking: true on the provider.
  4. Clean up duplicate users in the database and enforce one-account-per-user linking rules.

Example fix

// before
Google({ clientId, clientSecret })
// after (only if you understand the security tradeoff)
Google({ clientId, clientSecret, allowDangerousEmailAccountLinking: true })
Defensive patterns

Strategy: try-catch

Validate before calling

// Before offering account linking in your UI, check ownership:
const existing = await adapter.getAccountByProviderAccountId(provider, providerAccountId)
if (existing && existing.userId !== session.user.id) {
  throw new Error('This account is already linked to another user')
}

Try / catch

try {
  await signIn(providerId)
} catch (e) {
  if (e instanceof AccountNotLinked) {
    // show 'account already linked to another user' message / support path
  }
}

Prevention

When it happens

Trigger: Signing in with the same OAuth account under a second, different user session while allowDangerousEmailAccountLinking is off; two local users each having previously linked the same external account; database state where the account row's userId points to another user.

Common situations: Testing with the same Google/GitHub account across two test users; staging databases seeded with the same OAuth account on multiple users; switching auth providers and reusing a database with stale account rows.

Related errors


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