nextauthjs/next-auth · error

Missing or invalid provider account

Error message

Missing or invalid provider account

What it means

During the OAuth/email callback, handleLoginOrRegister validates the provider account object returned by the provider before linking or creating a user. If the account has no providerAccountId or no type, the flow cannot identify the account and throws this Error in packages/core/src/lib/actions/callback/handle-login.ts:34.

Source

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

 * linking (or not linking) accounts depending on if the user is currently logged
 * in, if they have account already and the authentication mechanism they are using.
 *
 * It prevents insecure behaviour, such as linking OAuth accounts unless a user is
 * signed in and authenticated with an existing valid account.
 *
 * All verification (e.g. OAuth flows or email address verification flows) are
 * done prior to this handler being called to avoid additional complexity in this
 * handler.
 */
export async function handleLoginOrRegister(
  sessionToken: SessionToken,
  _profile: User | AdapterUser | { email: string },
  _account: AdapterAccount | Account | null,
  options: InternalOptions
) {
  // Input validation
  if (!_account?.providerAccountId || !_account.type)
    throw new Error("Missing or invalid provider account")
  if (!["email", "oauth", "oidc", "webauthn"].includes(_account.type))
    throw new Error("Provider not supported")

  const {
    adapter,
    jwt,
    events,
    session: { strategy: sessionStrategy, generateSessionToken },
  } = options

  // If no adapter is configured then we don't have a database and cannot
  // persist data; in this mode we just return a dummy session object.
  if (!adapter) {
    return { user: _profile as User, account: _account as Account }
  }

  const profile = _profile as AdapterUser
  let account = _account as AdapterAccount

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. In your custom provider, always return an account with providerAccountId and type (e.g. 'oauth') from the getUserFromTokenset/profile callback.
  2. Check that the provider's token endpoint response actually contains an account identifier (sub / id) and map it to providerAccountId.
  3. Update @auth/core and the provider package to compatible versions so account normalization runs.

Example fix

// before (custom provider)
return { tokens: tokenset }
// after
return { token: tokenset, account: { providerAccountId: profile.sub, type: 'oauth', provider: 'myprovider' } }
Defensive patterns

Strategy: validation

Validate before calling

if (!account?.providerAccountId || !account?.type) {
  throw new Error('Custom provider returned an incomplete account')
}

Type guard

function isValidAccount(a: any): a is AdapterAccount {
  return !!a && typeof a.providerAccountId === 'string' && a.providerAccountId.length > 0 && typeof a.type === 'string' && ['email','oauth','oidc','webauthn'].includes(a.type)
}

Try / catch

try {
  await signIn('myprovider', ...)
} catch (e) {
  if ((e as Error).message === 'Missing or invalid provider account') {
    // inspect the custom provider's account mapping
  }
}

Prevention

When it happens

Trigger: A custom OAuth provider whose profile/account callback omits providerAccountId or type; a custom credentials-like flow that returns null or a malformed account to signIn; a provider returning an account object missing required AdapterAccount fields.

Common situations: Writing a custom OAuthProvider and forgetting to set providerAccountId in the account returned from the tokenset/profile step; using an older provider package that returns a different account shape; mis-wrapping a custom flow to call the internal callback action.

Related errors


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