{"record":{"id":"0ae1f770593994b2","repo":"nextauthjs/next-auth","slug":"webauthn-provider-requires-a-database-adapter-to-b","errorCode":null,"errorMessage":"WebAuthn provider requires a database adapter to be configured","messagePattern":"WebAuthn provider requires a database adapter to be configured","errorType":"exception","errorClass":"MissingAdapter","httpStatus":null,"severity":"error","filePath":"packages/core/src/providers/webauthn.ts","lineNumber":243,"sourceCode":"  }\n}\n\n/**\n * Retrieves user information for the WebAuthn provider.\n *\n * It looks for the \"email\" query parameter and uses it to look up the user in the database.\n * It also accepts a \"name\" query parameter to set the user's display name.\n *\n * @param options - The internaloptions object.\n * @param request - The request object containing the query parameters.\n * @returns The existing or new user info.\n * @throws {MissingAdapter} If the adapter is missing.\n * @throws {EmailSignInError} If the email address is not provided.\n */\nconst getUserInfo: GetUserInfo = async (options, request) => {\n  const { adapter } = options\n  if (!adapter)\n    throw new MissingAdapter(\n      \"WebAuthn provider requires a database adapter to be configured\"\n    )\n\n  // Get email address from the query.\n  const { query, body, method } = request\n  const email = (method === \"POST\" ? body?.email : query?.email) as unknown\n\n  // If email is not provided, return null\n  if (!email || typeof email !== \"string\") return null\n\n  const existingUser = await adapter.getUserByEmail(email)\n  if (existingUser) {\n    return { user: existingUser, exists: true }\n  }\n\n  // If the user does not exist, return a new user info.\n  return { user: { email }, exists: false }\n}","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/providers/webauthn.ts#L225-L261","documentation":"Auth.js's WebAuthn (passkey) provider stores and looks up authenticator credentials in the database, so it hard-requires a database adapter. getUserInfo throws MissingAdapter as soon as it sees options.adapter is undefined — i.e. the AuthConfig was set up without an adapter (or without Prisma/Drizzle/Mongoose etc. support) while including the WebAuthn provider.","triggerScenarios":"Any WebAuthn flow (registration or authentication POST/GET to /auth/callback/webauthn or /auth/webauthn endpoints) when the auth config has providers: [WebAuthn(...)] but no adapter is configured — typically a stateless setup (e.g. JWT-only, no database) that added passkey support.","commonSituations":"Developers add the WebAuthn provider to an existing credentials/OAuth-only Auth.js setup that never had a database; or they deploy with adapter code commented out / conditional so it's undefined in production; or they import the wrong auth configuration in a route handler.","solutions":["Configure a database adapter in your AuthConfig (e.g. PrismaAdapter, DrizzleAdapter) via the adapter option.","Add the required WebAuthn models (Authenticator table) to your database schema and regenerate the client.","If you don't need passkeys, remove the WebAuthn provider from the providers array.","Ensure the exported auth config used by route handlers actually includes the adapter (don't conditionally omit it)."],"exampleFix":"// before\nexport const { handlers, auth, signIn, signOut } = NextAuth({\n  providers: [WebAuthn({ enableUI: true })],\n})\n// after\nimport { PrismaAdapter } from \"@auth/prisma-adapter\"\nimport { prisma } from \"@/lib/prisma\"\nexport const { handlers, auth, signIn, signOut } = NextAuth({\n  adapter: PrismaAdapter(prisma),\n  providers: [WebAuthn({ enableUI: true })],\n})","handlingStrategy":"validation","validationCode":"// Fail fast at startup if WebAuthn is configured without an adapter:\nif (config.providers.some((p) => (p as { id?: string }).id === \"webauthn\") && !config.adapter) {\n  throw new Error(\"WebAuthn provider requires an adapter\")\n}","typeGuard":"function hasWebAuthnWithoutAdapter(config: { providers: { id?: string }[]; adapter?: unknown }): boolean {\n  return config.providers.some((p) => p.id === \"webauthn\") && !config.adapter\n}","tryCatchPattern":"try {\n  await signIn(\"webauthn\")\n} catch (err) {\n  if ((err as Error).message.includes(\"database adapter\")) {\n    console.error(\"Configure an adapter (e.g. PrismaAdapter) to use passkeys\")\n  }\n}","preventionTips":["Always pair the WebAuthn provider with an adapter in your auth config.","Add the Authenticator model to your schema before enabling passkeys.","Write a startup-time config test that asserts adapter presence when WebAuthn is enabled.","Remove the WebAuthn provider if your app is intentionally stateless."],"tags":["webauthn","adapter","configuration","database"],"backgroundTag":"missing-adapter","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}