{"record":{"id":"96016577a2056bc4","repo":"nextauthjs/next-auth","slug":"webauthn-account-not-found-in-database-json-str","errorCode":null,"errorMessage":"WebAuthn account not found in database: ${JSON.stringify({credentialID, providerAccountId: authenticator.providerAccountId})}","messagePattern":"WebAuthn account not found in database: (.+?)\\)\\}","errorType":"exception","errorClass":"AuthError","httpStatus":null,"severity":"error","filePath":"packages/core/src/lib/utils/webauthn-utils.ts","lineNumber":295,"sourceCode":"    throw new AdapterError(\n      `Failed to update authenticator counter. This may cause future authentication attempts to fail. ${JSON.stringify(\n        {\n          credentialID,\n          oldCounter: authenticator.counter,\n          newCounter: authenticationInfo.newCounter,\n        }\n      )}`,\n      e\n    )\n  }\n\n  // Get the account and user\n  const account = await adapter.getAccount(\n    authenticator.providerAccountId,\n    provider.id\n  )\n  if (!account) {\n    throw new AuthError(\n      `WebAuthn account not found in database: ${JSON.stringify({\n        credentialID,\n        providerAccountId: authenticator.providerAccountId,\n      })}`\n    )\n  }\n\n  const user = await adapter.getUser(account.userId)\n  if (!user) {\n    throw new AuthError(\n      `WebAuthn user not found in database: ${JSON.stringify({\n        credentialID,\n        providerAccountId: authenticator.providerAccountId,\n        userID: account.userId,\n      })}`\n    )\n  }\n","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/core/src/lib/utils/webauthn-utils.ts#L277-L313","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the Account table for the providerAccountId and provider.id pair","Ensure WebAuthn provider id matches what was used at registration","Fix or re-implement adapter.getAccount so it matches the account by providerAccountId and provider","Re-link the account or re-register the passkey if data is inconsistent"],"exampleFix":"// before\nprovider: { id: \"passkey\", ... } // registered under \"webauthn\"\n// after\nprovider: { id: \"webauthn\", ... } // match the original provider id","handlingStrategy":"validation","validationCode":"const account = await adapter.getAccount(authenticator.providerAccountId, provider.id)\nif (!account) {\n  // unlink the stale authenticator or re-link the account before authenticating\n}","typeGuard":null,"tryCatchPattern":"try {\n  await verifyAuthenticate(data)\n} catch (e) {\n  if (e instanceof AuthError && e.message.includes('account not found')) {\n    // clean up orphaned authenticator, prompt re-registration\n  }\n}","preventionTips":["Cascade account deletions to authenticators","Never change the WebAuthn provider id after go-live","Back up and restore the full relational graph, not partial tables","Test adapter.getAccount against your actual schema"],"tags":["webauthn","database","account","adapter"],"backgroundTag":"orphaned-authenticator-record","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}