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 AdapterAccountView on GitHub (pinned to a1a16a5a77)
Solutions
- In your custom provider, always return an account with providerAccountId and type (e.g. 'oauth') from the getUserFromTokenset/profile callback.
- Check that the provider's token endpoint response actually contains an account identifier (sub / id) and map it to providerAccountId.
- 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
- In custom providers, always map profile.sub (or equivalent) to providerAccountId.
- Type the account as AdapterAccount so TypeScript enforces required fields.
- Log the account object during development to verify its shape before production.
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
- Provider not supported
- Callback route called without provider
- OAuth Provider returned an error
- OAuth Provider returned an error: ${responseJson.error}
- token_type is 'bearer'. Redundant workaround, please open an
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/be48795865d3132c.
Report an issue: GitHub.