nextauthjs/next-auth · error · AdapterError
Failed to update authenticator counter. This may cause futur
Error message
Failed to update authenticator counter. This may cause future authentication attempts to fail. ${JSON.stringify({credentialID, oldCounter: authenticator.counter, newCounter: authenticationInfo.newCounter})} What it means
The credential verification succeeded, but updating the authenticator's signature counter via adapter.updateAuthenticatorCounter failed. The library escalates it to an AdapterError with details because a stale counter can cause future assertions to be rejected as cloned authenticators.
Source
Thrown at packages/core/src/lib/utils/webauthn-utils.ts:277
const { verified, authenticationInfo } = verification
// Make sure the response was verified
if (!verified) {
throw new WebAuthnVerificationError(
"WebAuthn authentication response could not be verified"
)
}
// Update authenticator counter
try {
const { newCounter } = authenticationInfo
await adapter.updateAuthenticatorCounter(
authenticator.credentialID,
newCounter
)
} catch (e: any) {
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(View on GitHub (pinned to a1a16a5a77)
Solutions
- Check database connectivity and adapter error logs for the root cause
- Implement updateAuthenticatorCounter in your custom adapter if missing
- Verify the Authenticator table still has a counter column in your schema
- Re-run authentication once the adapter write path is healthy
Example fix
// before
// adapter missing updateAuthenticatorCounter -> AdapterError
// after
async updateAuthenticatorCounter(credentialID, counter) {
await db.authenticator.update({ where: { credentialID }, data: { counter } })
} Defensive patterns
Strategy: try-catch
Validate before calling
if (typeof adapter.updateAuthenticatorCounter !== 'function') {
throw new Error('Adapter must implement updateAuthenticatorCounter')
} Try / catch
try {
await verifyAuthenticate(data)
} catch (e) {
if (e instanceof AdapterError && e.message.includes('authenticator counter')) {
logger.error(e.message) // auth succeeded but counter stale; alert ops
} else { throw e }
} Prevention
- Implement all AuthenticatorFramework adapter methods when writing custom adapters
- Keep the counter column in your schema migrations
- Watch database connectivity and pool health
- Alert on this error since stale counters can block future logins
When it happens
Trigger: updateAuthenticatorCounter throws inside verifyAuthenticate — adapter not connected, DB write error, or a custom adapter that doesn't implement updateAuthenticatorCounter.
Common situations: Database connection pool exhausted or down at write time; custom adapter missing the updateAuthenticatorCounter method; schema migration removed the counter column; permissions preventing updates.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- WebAuthn authenticator not found in database: ${JSON.stringi
- WebAuthn account not found in database: ${JSON.stringify({cr
- An adapter is required for the WebAuthn provider
- WebAuthn provider requires a database adapter to be configur
- Unable to update authenticator with credential ${credentialI
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/59340948a18402eb.
Report an issue: GitHub.