nextauthjs/next-auth · error · AuthError

WebAuthn account not found in database: ${JSON.stringify({cr

Error message

WebAuthn account not found in database: ${JSON.stringify({credentialID, providerAccountId: authenticator.providerAccountId})}

What it means

After finding the authenticator, verifyAuthenticate fetches the linked account via adapter.getAccount(authenticator.providerAccountId, provider.id). If no account row exists for that provider account, authentication cannot resolve to a user, so this AuthError is thrown with the credentialID and providerAccountId for debugging.

Source

Thrown at packages/core/src/lib/utils/webauthn-utils.ts:295

    throw new AdapterError(
      `Failed to update authenticator counter. This may cause future authentication attempts to fail. ${JSON.stringify(
        {
          credentialID,
          oldCounter: authenticator.counter,
          newCounter: authenticationInfo.newCounter,
        }
      )}`,
      e
    )
  }

  // Get the account and user
  const account = await adapter.getAccount(
    authenticator.providerAccountId,
    provider.id
  )
  if (!account) {
    throw new AuthError(
      `WebAuthn account not found in database: ${JSON.stringify({
        credentialID,
        providerAccountId: authenticator.providerAccountId,
      })}`
    )
  }

  const user = await adapter.getUser(account.userId)
  if (!user) {
    throw new AuthError(
      `WebAuthn user not found in database: ${JSON.stringify({
        credentialID,
        providerAccountId: authenticator.providerAccountId,
        userID: account.userId,
      })}`
    )
  }

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Check the Account table for the providerAccountId and provider.id pair
  2. Ensure WebAuthn provider id matches what was used at registration
  3. Fix or re-implement adapter.getAccount so it matches the account by providerAccountId and provider
  4. Re-link the account or re-register the passkey if data is inconsistent

Example fix

// before
provider: { id: "passkey", ... } // registered under "webauthn"
// after
provider: { id: "webauthn", ... } // match the original provider id
Defensive patterns

Strategy: validation

Validate before calling

const account = await adapter.getAccount(authenticator.providerAccountId, provider.id)
if (!account) {
  // unlink the stale authenticator or re-link the account before authenticating
}

Try / catch

try {
  await verifyAuthenticate(data)
} catch (e) {
  if (e instanceof AuthError && e.message.includes('account not found')) {
    // clean up orphaned authenticator, prompt re-registration
  }
}

Prevention

When it happens

Trigger: The authenticator exists but its providerAccountId no longer maps to an Account row — account deleted, provider id changed, or adapter returning null for a valid lookup due to schema/encoding mismatch.

Common situations: Users deleting their OAuth/account link while the passkey remains; custom adapters that don't implement getAccount properly; provider id changed in AuthConfig (e.g. from 'webauthn' to a custom id); database restored partially from backup.

Understand the failure class

Related errors


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