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
- 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.
- Sign in with the user that already owns the OAuth account instead of creating a second one.
- If email-verified linking is acceptable, set allowDangerousEmailAccountLinking: true on the provider.
- 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
- Add a unique constraint on (provider, provider_account_id) in your accounts table.
- Provide an unlink-account UI backed by your adapter.
- Decide explicitly whether to enable allowDangerousEmailAccountLinking.
- Clean duplicate users from seeded/staging databases regularly.
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
- Another account already exists with the same e-mail address
- Error creating user: Cannot get user after creation.
- Error updating user: Cannot get user after updating.
- Error updating user: Failed to run the update SQL.
- Couldn't create session
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/4129a578bb7cdae4.
Report an issue: GitHub.