This error occurs when unlinking an identity would cause a user's account to switch to an email address that's already in use by another user. Supabase enforces unique email addresses across all user accounts.
Supabase Auth maintains a constraint that every email address in your user database must be unique. When you attempt to unlink an identity from a user, Supabase checks if removing that identity would require the account to change to a different email address that's already claimed by another user. This error specifically indicates that: 1. The user has multiple identities linked (e.g., email/password + Google OAuth) 2. The identities are associated with different email addresses 3. When you try to unlink one identity, the account would need to use the email from another identity 4. That target email is already assigned to a different user account This situation typically arises when a user previously signed up with one email address, later linked a different authentication provider with a different email, and now is trying to unlink the original identity. Supabase won't allow this because it would orphan the secondary email or create a conflict.
First, check what identities and email addresses are associated with the user account:
const { data: { user }, error } = await supabase.auth.getUser();
if (user?.identities) {
user.identities.forEach(identity => {
console.log(`Provider: ${identity.provider}`);
console.log(`Identity ID: ${identity.id}`);
console.log(`Email: ${identity.email || 'No email'}`);
console.log(`Identity data:`, identity);
});
}
// Also check the user's primary email
console.log(`Primary email: ${user?.email}`);This will show you all linked authentication methods and their associated email addresses.
The email conflict means the email you're trying to assign to this account is already in use. You need to verify which other user owns that email:
// Using the Admin API (requires service_role key)
import { createClient } from "@supabase/supabase-js";
const adminClient = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY
);
const { data: users } = await adminClient.auth.admin.listUsers();
const conflictUser = users.find(u => u.email === '[email protected]');
console.log('User with conflicting email:', conflictUser);Once you've identified the other user, you can decide on a resolution strategy.
The safest resolution is to change the email address on one of the conflicting accounts so they're no longer duplicates:
// Option A: Update your current user's email to something unique
const { data, error } = await supabase.auth.updateUser({
email: '[email protected]'
});
if (error) {
console.error('Error updating email:', error);
} else {
console.log('Email updated successfully');
// User will receive a confirmation email
}
// Option B: If you have admin access, update the other user
const adminClient = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY
);
await adminClient.auth.admin.updateUserById('other-user-id', {
email: '[email protected]'
});After changing one of the email addresses, the conflict should be resolved and you can retry the identity unlinking.
Once the email addresses are no longer in conflict, attempt to unlink the identity again:
const { data, error } = await supabase.auth.unlinkIdentity({
identity_id: 'identity-to-unlink'
});
if (error) {
if (error.message.includes('email_conflict_identity_not_deletable')) {
console.error('Email conflict still exists. Verify all emails are unique.');
} else {
console.error('Different error occurred:', error);
}
} else {
console.log('Identity unlinked successfully');
// Refresh user data
const { data: { user: updatedUser } } = await supabase.auth.getUser();
console.log('Updated user identities:', updatedUser?.identities);
}In some cases, users may have legitimately created multiple accounts with different emails. If you want to consolidate them:
// Using Admin API
const adminClient = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY
);
// 1. Identify both user accounts
const user1Id = 'primary-account-id';
const user2Id = 'secondary-account-id';
// 2. Migrate any data from user2 to user1 in your custom tables
await supabase
.from('user_profiles')
.update({ user_id: user1Id })
.eq('user_id', user2Id);
await supabase
.from('user_posts')
.update({ user_id: user1Id })
.eq('user_id', user2Id);
// 3. Delete the secondary account
await adminClient.auth.admin.deleteUser(user2Id);
console.log('Account migration completed');This approach consolidates the user data under one account, eliminating the email conflict entirely.
Email uniqueness is a fundamental constraint in Supabase Auth. Unlike some identity providers that allow multiple accounts with the same email address, Supabase enforces a one-to-one relationship between user IDs and email addresses.
The error occurs at the time of unlinking because Supabase needs to ensure that after the identity removal, the user still has a valid, unique email address. If the only way to maintain a valid email is to use an address already claimed by another user, the operation is rejected.
When using Manual Identity Linking, be cautious about linking identities from different email addresses. If you need to link multiple OAuth providers to one account, ensure they're registered with the same email address on those providers, or ensure you update one email address before attempting the unlink.
For users managing multiple accounts, the recommended approach is either:
1. Update one email to be unique before unlinking
2. Merge the accounts by migrating data and deleting the secondary account
3. Keep both accounts but with different email addresses (don't try to unlink in this case)
mfa_challenge_expired: MFA challenge has expired
How to fix "mfa_challenge_expired: MFA challenge has expired" in Supabase
conflict: Database conflict, usually related to concurrent requests
How to fix "database conflict usually related to concurrent requests" in Supabase
phone_exists: Phone number already exists
How to fix "phone_exists" in Supabase
StorageApiError: resource_already_exists
StorageApiError: Resource already exists
email_address_not_authorized: Email sending to this address is not authorized
Email address not authorized for sending in Supabase Auth