nextauthjs/next-auth · error · MissingAdapter
An adapter is required for the WebAuthn provider
Error message
An adapter is required for the WebAuthn provider
What it means
Auth.js throws MissingAdapter when the WebAuthn passkey provider is configured but no database adapter is supplied. The WebAuthn provider must persist credentials (authenticators) and challenges, so an adapter (Prisma, Drizzle, MongoDB, etc.) is mandatory. assertInternalOptionsWebAuthn validates this early when building the WebAuthn route handlers.
Source
Thrown at packages/core/src/lib/utils/webauthn-utils.ts:489
userDisplayName: user.name ?? undefined,
rpID: relayingParty.id,
rpName: relayingParty.name,
excludeCredentials: authenticators?.map((a) => ({
id: fromBase64(a.credentialID),
type: "public-key",
transports: stringToTransports(a.transports),
})),
})
}
export function assertInternalOptionsWebAuthn(
options: InternalOptions
): InternalOptionsWebAuthn {
const { provider, adapter } = options
// Adapter is required for WebAuthn
if (!adapter)
throw new MissingAdapter("An adapter is required for the WebAuthn provider")
// Provider must be WebAuthn
if (!provider || provider.type !== "webauthn") {
throw new InvalidProvider("Provider must be WebAuthn")
}
// Narrow the options type for typed usage later
return { ...options, provider, adapter }
}
function fromAdapterAuthenticator(
authenticator: AdapterAuthenticator
): InternalAuthenticator {
return {
...authenticator,
credentialDeviceType:
authenticator.credentialDeviceType as InternalAuthenticator["credentialDeviceType"],
transports: stringToTransports(authenticator.transports),
credentialID: fromBase64(authenticator.credentialID),
credentialPublicKey: fromBase64(authenticator.credentialPublicKey),View on GitHub (pinned to a1a16a5a77)
Solutions
- Add a database adapter to your Auth.js config (e.g. `adapter: PrismaAdapter(prisma)`) — WebAuthn credentials cannot work without persistent storage.
- Verify your adapter actually initializes: check DATABASE_URL / connection env vars so the adapter isn't undefined at runtime.
- Confirm you are using an adapter that supports WebAuthn tables (Authenticator model); update the adapter package and run its schema push/migrations.
- If you don't want a database, do not enable the WebAuthn provider; use a standard credentials/OAuth provider instead.
Example fix
// before
export const { handlers, auth, signIn, signOut } = NextAuth({
providers: [Passkey()],
})
// after
import { PrismaAdapter } from "@auth/prisma-adapter"
import { prisma } from "@/lib/db"
export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma),
providers: [Passkey()],
}) Defensive patterns
Strategy: validation
Validate before calling
if (!options.adapter) {
throw new Error("WebAuthn provider requires a database adapter in your Auth.js config")
} Type guard
function hasAdapter(o: { adapter?: unknown }): o is { adapter: NonNullable<unknown> } {
return o.adapter != null
} Try / catch
try {
const webAuthnOptions = assertInternalOptionsWebAuthn(options)
} catch (e) {
if (e instanceof MissingAdapter) {
throw new ConfigError("Add an adapter (e.g. PrismaAdapter) — WebAuthn requires persistent storage")
}
throw e
} Prevention
- Always configure an adapter when enabling the WebAuthn/Passkey provider
- Add a startup-time config check that fails fast if provider type is webauthn but adapter is missing
- Keep adapter packages and their schema migrations in sync with your Auth.js version
- Verify DATABASE_URL and adapter initialization in CI before deploying
When it happens
Trigger: Calling localOptions or narrowOptions (which call assertInternalOptionsWebAuthn) with an InternalOptions object whose `adapter` property is undefined/missing while provider.type is "webauthn" — e.g. building the WebAuthn provider route handlers without an adapter in the Auth.js config.
Common situations: Using the Passkey/WebAuthn provider in a credentials-only setup with no database; forgetting to pass `adapter` when manually constructing options; an adapter plugin failing to initialize (e.g. missing DATABASE_URL so the adapter is never created); upgrading Auth.js and a previously implicit adapter wiring is now explicit.
Related errors
- WebAuthn provider requires a database adapter to be configur
- WebAuthn authenticator not found in database: ${JSON.stringi
- Failed to update authenticator counter. This may cause futur
- WebAuthn account not found in database: ${JSON.stringify({cr
- Unable to update authenticator with credential ${credentialI
AI-assisted analysis of nextauthjs/next-auth@a1a16a5a77 (2026-08-28).
Data as JSON: /api/errors/bf6369e435e7d6c4.
Report an issue: GitHub.