error:unable_to_link_account #2671

Closed
opened 2026-03-13 10:12:20 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @aman-a-dev on GitHub (Jan 8, 2026).

Is this suited for github?

  • Yes, this is suited for github

To Reproduce

Google 0Auth

Current vs. Expected behavior

The error is that when I try to continue wwith Google that is

const handleGoogleSignIn = async () => {
      try {
         setGoogleLoading(true)

         const res = await authClient.signIn.social({
            provider: 'google',
            callbackURL: '/dashboard',
            errorCallbackURL: '/auth/error',
            //storeAccessToken: false
         })

         if (res.error) {
            toast.error('Google sign-in failed', {
               description: res.error.message || 'Please try again'
            })
            setGoogleLoading(false)
            return
         }

         // If successful, auth flow will handle the redirect
         // No need for manual redirect here
      } catch (error) {
         console.error('Google sign-in error:', error)
         toast.error('Sign-in failed', {
            description: 'Please try again'
         })
         setGoogleLoading(false)
      }
   }

I go to Google site -> choose an account-> after I finish it redirect me to http://localhost:3000/auth/error?error=unable_to_link_account

bash full log

(compile: 245ms, render: 217ms)
 GET /auth/error?error=unable_to_link_account 404 in 922ms (compile: 291ms, render: 631ms)

What version of Better Auth are you using?

1.4.5

System info

Alpine Linux

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

Other

Auth config (if applicable)

// auth
import { betterAuth } from 'better-auth'
// orm
import { prismaAdapter } from 'better-auth/adapters/prisma'
import { prisma } from './prisma'
// email
import { Resend } from 'resend'
const resend = new Resend(process.env.RESEND_API_KEY)
// plugins
import { customSession } from 'better-auth/plugins'

export const auth = betterAuth({
   baseURL: process.env.BETTER_AUTH_URL,
   database: prismaAdapter(prisma, {
      provider: 'mysql'
   }),
   account: {
      accountLinking: {
         enabled: true
      }
   },
   emailAndPassword: {
      enabled: true,
      requireEmailVerification: true,
      sendOnSignUp: true
   },
   socialProviders: {
      google: {
         accessType: 'offline',
         prompt: 'select_account consent',
         clientId: process.env.AUTH_GOOGLE_CLIENT_ID as string,
         clientSecret: process.env.AUTH_GOOGLE_CLIENT_SECRET as string
      }
   },
   advanced: {
      cookiePrefix: 'hyper-chat'
   },
   user: {
      changeEmail: {
         enabled: true
      },
      deleteUser: {
         enabled: true,
         sendDeleteAccountVerification: async (
            { user, url, token },
            request
         ) => {
            const { error } = await resend.emails.send({
               from: 'Hyper-Chat <onboarding@yourdomain.com>',
               to: user.email,
               subject: 'Delete Hyperchat account',
               html: `
        <div style="display:flex;justify-content:center;text-align:center;flex-direction: column;align-items:center">
          <h1 style="font-weight: bold;color: #cab300;">Delete Hyper-Chat Account ️🗑</h1>
          <p>Please click the link below 👇 to confirm Delete Account</p>
          <a href="${url}" style="background-color:#FFD700;color:white;padding:10px 20px;text-decoration:none;border-radius:5px;max-width: 300px;">Verify my Email</a>
          <p><b>${user.email}</b> Delete my account</p>
          <p>If you didn't request this, please ignore this email.</p>
        </div>
        `
            })
         }
      }
   },
   emailVerification: {
      sendVerificationEmail: async ({ user, url }) => {
         const { error } = await resend.emails.send({
            from: 'Hyper-Chat <onboarding@hyper-chat.com>',
            to: user.email,
            subject: 'Verify your email address',
            html: `
        <div style="display:flex;justify-content:center;text-align:center;flex-direction: column;align-items:center">
          <h1 style="font-weight: bold;color: #cab300;">Welcome to Hyper-Chat ✋️</h1>
          <p>Please click the link below 👇 to verify your email address:</p>
          <a href="${url}" style="background-color:#FFD700;color:white;padding:10px 20px;text-decoration:none;border-radius:5px;max-width: 300px;">Verify my Email</a>
          <p><b>${user.email}</b> is going  to verify</p>
          <p>If you didn't request this, please ignore this email.</p>
        </div>
        `
         })

         if (error) {
            console.error('Failed to send verification email:', error)
         }
      }
   },
   user: {
      additionalFields: {
         bio: {
            type: 'string',
            required: false,
            input: false
         },
         job: {
            type: 'string',
            required: false,
            input: false
         },
         country: {
            type: 'string',
            required: false,
            input: false
         }
      }
   },
   plugins: [
      customSession(async ({ user, session }) => {
         return {
            user: {
               ...user,
               bio: user.bio,
               job: user.job,
               country: user.country
            },
            session
         }
      })
   ]
})

Additional context

No response

Originally created by @aman-a-dev on GitHub (Jan 8, 2026). ### Is this suited for github? - [x] Yes, this is suited for github ### To Reproduce Google 0Auth ### Current vs. Expected behavior The error is that when I try to continue wwith **Google** that is ```tsx const handleGoogleSignIn = async () => { try { setGoogleLoading(true) const res = await authClient.signIn.social({ provider: 'google', callbackURL: '/dashboard', errorCallbackURL: '/auth/error', //storeAccessToken: false }) if (res.error) { toast.error('Google sign-in failed', { description: res.error.message || 'Please try again' }) setGoogleLoading(false) return } // If successful, auth flow will handle the redirect // No need for manual redirect here } catch (error) { console.error('Google sign-in error:', error) toast.error('Sign-in failed', { description: 'Please try again' }) setGoogleLoading(false) } } ``` I go to Google site -> choose an account-> after I finish it redirect me to http://localhost:3000/auth/error?error=unable_to_link_account # bash full log ```bash (compile: 245ms, render: 217ms) GET /auth/error?error=unable_to_link_account 404 in 922ms (compile: 291ms, render: 631ms) ``` ### What version of Better Auth are you using? 1.4.5 ### System info ```bash Alpine Linux ``` ### Which area(s) are affected? (Select all that apply) Other ### Auth config (if applicable) ```typescript // auth import { betterAuth } from 'better-auth' // orm import { prismaAdapter } from 'better-auth/adapters/prisma' import { prisma } from './prisma' // email import { Resend } from 'resend' const resend = new Resend(process.env.RESEND_API_KEY) // plugins import { customSession } from 'better-auth/plugins' export const auth = betterAuth({ baseURL: process.env.BETTER_AUTH_URL, database: prismaAdapter(prisma, { provider: 'mysql' }), account: { accountLinking: { enabled: true } }, emailAndPassword: { enabled: true, requireEmailVerification: true, sendOnSignUp: true }, socialProviders: { google: { accessType: 'offline', prompt: 'select_account consent', clientId: process.env.AUTH_GOOGLE_CLIENT_ID as string, clientSecret: process.env.AUTH_GOOGLE_CLIENT_SECRET as string } }, advanced: { cookiePrefix: 'hyper-chat' }, user: { changeEmail: { enabled: true }, deleteUser: { enabled: true, sendDeleteAccountVerification: async ( { user, url, token }, request ) => { const { error } = await resend.emails.send({ from: 'Hyper-Chat <onboarding@yourdomain.com>', to: user.email, subject: 'Delete Hyperchat account', html: ` <div style="display:flex;justify-content:center;text-align:center;flex-direction: column;align-items:center"> <h1 style="font-weight: bold;color: #cab300;">Delete Hyper-Chat Account ️🗑</h1> <p>Please click the link below 👇 to confirm Delete Account</p> <a href="${url}" style="background-color:#FFD700;color:white;padding:10px 20px;text-decoration:none;border-radius:5px;max-width: 300px;">Verify my Email</a> <p><b>${user.email}</b> Delete my account</p> <p>If you didn't request this, please ignore this email.</p> </div> ` }) } } }, emailVerification: { sendVerificationEmail: async ({ user, url }) => { const { error } = await resend.emails.send({ from: 'Hyper-Chat <onboarding@hyper-chat.com>', to: user.email, subject: 'Verify your email address', html: ` <div style="display:flex;justify-content:center;text-align:center;flex-direction: column;align-items:center"> <h1 style="font-weight: bold;color: #cab300;">Welcome to Hyper-Chat ✋️</h1> <p>Please click the link below 👇 to verify your email address:</p> <a href="${url}" style="background-color:#FFD700;color:white;padding:10px 20px;text-decoration:none;border-radius:5px;max-width: 300px;">Verify my Email</a> <p><b>${user.email}</b> is going to verify</p> <p>If you didn't request this, please ignore this email.</p> </div> ` }) if (error) { console.error('Failed to send verification email:', error) } } }, user: { additionalFields: { bio: { type: 'string', required: false, input: false }, job: { type: 'string', required: false, input: false }, country: { type: 'string', required: false, input: false } } }, plugins: [ customSession(async ({ user, session }) => { return { user: { ...user, bio: user.bio, job: user.job, country: user.country }, session } }) ] }) ``` ### Additional context _No response_
GiteaMirror added the social-provider label 2026-03-13 10:12:20 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Jan 8, 2026):

It looks like you're encountering an "unable_to_link_account" error when trying to sign in with Google using Better Auth, even though you've set up your account linking configuration. Here are a few steps to troubleshoot this issue:

  1. Check Account Linking Configuration: Ensure that the accountLinking option is set to { enabled: true }. If linking is disabled, no accounts can be linked, regardless of the provider's email verification status [5].

  2. Verify Trusted Providers: If you're using multiple social providers, make sure that the provider you're trying to use (in this case, Google) is included in the trustedProviders list, if that's a requirement based on your security settings [5].

  3. Manual Linking: As mentioned in the provided context, manual linking might be necessary if the automatic linking is blocked due to conflicting accounts. Users logged in via other methods should be able to explicitly link their accounts when using authClient.linkSocial [2].

  4. Error Callback URL: Confirm that your errorCallbackURL is correctly set and handled in your application. This URL is where users will be redirected in case of an error, and ensuring it's configured may help in managing errors more effectively.

  5. Review OAuth Settings: Make sure your OAuth settings in Google Cloud Console (like allowed redirect URIs) match what you've configured in your application [1].

If you continue facing issues after verifying these configurations, consider reviewing open issues related to this error, as there might be relevant discussions or similar scenarios shared by the community.

If none of this resolves your issue, I recommend tagging @bekacru or @ping__ for further assistance from the Better Auth team!

Have you had a chance to verify these settings already? How is your current implementation going?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

@better-auth-agent[bot] commented on GitHub (Jan 8, 2026): It looks like you're encountering an "unable_to_link_account" error when trying to sign in with Google using Better Auth, even though you've set up your account linking configuration. Here are a few steps to troubleshoot this issue: 1. **Check Account Linking Configuration**: Ensure that the `accountLinking` option is set to `{ enabled: true }`. If linking is disabled, no accounts can be linked, regardless of the provider's email verification status [[5]](https://www.better-auth.com/docs/concepts/users-accounts). 2. **Verify Trusted Providers**: If you're using multiple social providers, make sure that the provider you're trying to use (in this case, Google) is included in the `trustedProviders` list, if that's a requirement based on your security settings [[5]](https://www.better-auth.com/docs/concepts/users-accounts). 3. **Manual Linking**: As mentioned in the provided context, manual linking might be necessary if the automatic linking is blocked due to conflicting accounts. Users logged in via other methods should be able to explicitly link their accounts when using `authClient.linkSocial` [[2]](https://github.com/better-auth/better-auth/issues/6392). 4. **Error Callback URL**: Confirm that your `errorCallbackURL` is correctly set and handled in your application. This URL is where users will be redirected in case of an error, and ensuring it's configured may help in managing errors more effectively. 5. **Review OAuth Settings**: Make sure your OAuth settings in Google Cloud Console (like allowed redirect URIs) match what you've configured in your application [[1]](https://github.com/better-auth/better-auth/issues/2172). If you continue facing issues after verifying these configurations, consider reviewing open issues related to this error, as there might be relevant discussions or similar scenarios shared by the community. If none of this resolves your issue, I recommend tagging @bekacru or @ping__ for further assistance from the Better Auth team! Have you had a chance to verify these settings already? How is your current implementation going? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@dosubot[bot] commented on GitHub (Jan 8, 2026):

Hi @aman-a-dev! I'm Dosu and I’m helping the better-auth team.

The error means Better Auth couldn't link the Google account to a user. This usually happens if (1) the provider isn't in your trustedProviders list and the email from Google isn't verified, or (2) there's a config/database mismatch. Here’s what to check:

  • Make sure the Google account’s email is verified. If not, linking will be denied unless you add Google to account.accountLinking.trustedProviders (details).
  • Your callbackURL in signIn.social should be a full absolute URL (e.g., http://localhost:3000/dashboard) if your frontend and backend are on different origins. Relative URLs can break the redirect and linking (reference).
  • Add your frontend domain (e.g., http://localhost:3000) to trustedOrigins in your Better Auth config (reference).
  • Check your database schema: the account table must include all required fields (like scope). Missing fields can cause this error (reference).
  • In v1.4.5, set the OAuth state cookie to SameSite=None and Secure=true in your config to avoid cookie issues that break OAuth flows (workaround):
    advanced: {
      cookies: {
        state: {
          attributes: {
            sameSite: "none",
            secure: true,
          }
        }
      }
    }
    
  • Make sure you’re not running custom middleware before the auth handler on /auth/* routes, as this can break cookie propagation and cause linking errors (reference).

If you’ve checked all of the above and still see the error, look for duplicate/conflicting user or account records in your database, and consider enabling more detailed backend logging for clues. Recent versions of Better Auth have improved account linking and OAuth token handling, so upgrading may help if you’re able to do so (reference).

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

@dosubot[bot] commented on GitHub (Jan 8, 2026): <!-- Greeting --> Hi @aman-a-dev! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> The error means Better Auth couldn't link the Google account to a user. This usually happens if (1) the provider isn't in your trustedProviders list and the email from Google isn't verified, or (2) there's a config/database mismatch. Here’s what to check: - Make sure the Google account’s email is verified. If not, linking will be denied unless you add Google to account.accountLinking.trustedProviders ([details](https://github.com/better-auth/better-auth/pull/6618)). - Your callbackURL in signIn.social should be a full absolute URL (e.g., http://localhost:3000/dashboard) if your frontend and backend are on different origins. Relative URLs can break the redirect and linking ([reference](https://github.com/better-auth/better-auth/issues/3289)). - Add your frontend domain (e.g., http://localhost:3000) to trustedOrigins in your Better Auth config ([reference](https://github.com/better-auth/better-auth/discussions/5253)). - Check your database schema: the account table must include all required fields (like scope). Missing fields can cause this error ([reference](https://github.com/better-auth/better-auth/issues/620)). - In v1.4.5, set the OAuth state cookie to SameSite=None and Secure=true in your config to avoid cookie issues that break OAuth flows ([workaround](https://github.com/better-auth/better-auth/issues/6483)): ```ts advanced: { cookies: { state: { attributes: { sameSite: "none", secure: true, } } } } ``` - Make sure you’re not running custom middleware before the auth handler on /auth/* routes, as this can break cookie propagation and cause linking errors ([reference](https://github.com/better-auth/better-auth/issues/5478)). If you’ve checked all of the above and still see the error, look for duplicate/conflicting user or account records in your database, and consider enabling more detailed backend logging for clues. Recent versions of Better Auth have improved account linking and OAuth token handling, so upgrading may help if you’re able to do so ([reference](https://github.com/better-auth/better-auth/pull/6874)). <!-- 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/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/bcc921e5-f4ac-4b2c-83bf-57a4d57b82fb?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=The%20error%20means%20Better%20Auth%20couldn%27t%20link%20the%20Google%20account%20to%20a%20user.%20This%20usually%20happens%20if%20%281%29%20the%20provider%20isn%27t%20in%20your%20trustedProviders%20list%20and%20the%20email%20from%20Google%20isn%27t%20verified%2C%20or%20%282%29%20there%27s%20a%20config/database%20mismatch.%20Here%E2%80%99s%20what%20to%20check%3A%0A%0A-%20Make%20sure%20the%20Google%20account%E2%80%99s%20email%20is%20verified.%20If%20not%2C%20linking%20will%20be%20denied%20unless%20you%20add%20Google%20to%20account.accountLinking.trustedProviders%C2%A0%28%5Bdetails%5D%28https%3A//github.com/better-auth/better-auth/pull/6618%29%29.%0A-%20Your%20callbackURL%20in%20signIn.social%20should%20be%20a%20full%20absolute%20URL%20%28e.g.%2C%20http%3A//localhost%3A3000/dashboard%29%20if%20your%20frontend%20and%20backend%20are%20on%20different%20origins.%20Relative%20URLs%20can%20break%20the%20redirect%20and%20linking%C2%A0%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/3289%29%29.%0A-%20Add%20your%20frontend%20domain%20%28e.g.%2C%20http%3A//localhost%3A3000%29%20to%20trustedOrigins%20in%20your%20Better%20Auth%20config%C2%A0%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/discussions/5253%29%29.%0A-%20Check%20your%20database%20schema%3A%20the%20account%20table%20must%20include%20all%20required%20fields%20%28like%20scope%29.%20Missing%20fields%20can%20cause%20this%20error%C2%A0%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/620%29%29.%0A-%20In%20v1.4.5%2C%20set%20the%20OAuth%20state%20cookie%20to%20SameSite%3DNone%20and%20Secure%3Dtrue%20in%20your%20config%20to%20avoid%20cookie%20issues%20that%20break%20OAuth%20flows%20%28%5Bworkaround%5D%28https%3A//github.com/better-auth/better-auth/issues/6483%29%29%3A%0A%20%20%60%60%60ts%0A%20%20advanced%3A%20%7B%0A%20%20%20%20cookies%3A%20%7B%0A%20%20%20%20%20%20state%3A%20%7B%0A%20%20%20%20%20%20%20%20attributes%3A%20%7B%0A%20%20%20%20%20%20%20%20%20%20sameSite%3A%20%22none%22%2C%0A%20%20%20%20%20%20%20%20%20%20secure%3A%20true%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%20%20%7D%0A%20%20%60%60%60%0A-%20Make%20sure%20you%E2%80%99re%20not%20running%20custom%20middleware%20before%20the%20auth%20handler%20on%20/auth/%2A%20routes%2C%20as%20this%20can%20break%20cookie%20propagation%20and%20cause%20linking%20errors%C2%A0%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/issues/5478%29%29.%0A%0AIf%20you%E2%80%99ve%20checked%20all%20of%20the%20above%20and%20still%20see%20the%20error%2C%20look%20for%20duplicate/conflicting%20user%20or%20account%20records%20in%20your%20database%2C%20and%20consider%20enabling%20more%20detailed%20backend%20logging%20for%20clues.%20Recent%20versions%20of%20Better%20Auth%20have%20improved%20account%20linking%20and%20OAuth%20token%20handling%2C%20so%20upgrading%20may%20help%20if%20you%E2%80%99re%20able%20to%20do%20so%C2%A0%28%5Breference%5D%28https%3A//github.com/better-auth/better-auth/pull/6874%29%29.)&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/7205)
Author
Owner

@bytaesu commented on GitHub (Jan 9, 2026):

Hello @aman-a-dev,

Since you're using both emailAndPassword and Google OAuth, you need to configure trustedProviders.
Please refer to the link below for more details 🙂

https://www.better-auth.com/docs/errors/unable_to_link_account

If your issue persists, feel free to reopen this issue or mention me!

@bytaesu commented on GitHub (Jan 9, 2026): Hello @aman-a-dev, Since you're using both emailAndPassword and Google OAuth, you need to configure `trustedProviders`. Please refer to the link below for more details 🙂 https://www.better-auth.com/docs/errors/unable_to_link_account If your issue persists, feel free to reopen this issue or mention me!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#2671