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

  1. Add a database adapter to your Auth.js config (e.g. `adapter: PrismaAdapter(prisma)`) — WebAuthn credentials cannot work without persistent storage.
  2. Verify your adapter actually initializes: check DATABASE_URL / connection env vars so the adapter isn't undefined at runtime.
  3. Confirm you are using an adapter that supports WebAuthn tables (Authenticator model); update the adapter package and run its schema push/migrations.
  4. 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

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


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