{"record":{"id":"8391e9e27dee4b8e","repo":"nextauthjs/next-auth","slug":"authenticator-not-found","errorCode":null,"errorMessage":"Authenticator not found.","messagePattern":"Authenticator not found\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/adapter-drizzle/src/lib/mysql.ts","lineNumber":374,"sourceCode":"      return (await client\n        .select()\n        .from(authenticatorsTable)\n        .where(eq(authenticatorsTable.userId, userId))\n        .then((res) => res)) as Awaitable<AdapterAuthenticator[]>\n    },\n    async updateAuthenticatorCounter(credentialID: string, newCounter: number) {\n      await client\n        .update(authenticatorsTable)\n        .set({ counter: newCounter })\n        .where(eq(authenticatorsTable.credentialID, credentialID))\n\n      const authenticator = await client\n        .select()\n        .from(authenticatorsTable)\n        .where(eq(authenticatorsTable.credentialID, credentialID))\n        .then((res) => res[0])\n\n      if (!authenticator) throw new Error(\"Authenticator not found.\")\n\n      return authenticator as Awaitable<AdapterAuthenticator>\n    },\n  }\n}\n\ntype DefaultMyqlColumn<\n  T extends {\n    data: string | number | boolean | Date\n    dataType: \"string\" | \"number\" | \"boolean\" | \"date\"\n    notNull: boolean\n    isPrimaryKey?: boolean\n    columnType:\n      | \"MySqlVarChar\"\n      | \"MySqlText\"\n      | \"MySqlBoolean\"\n      | \"MySqlTimestamp\"\n      | \"MySqlInt\"","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/nextauthjs/next-auth/blob/a1a16a5a7780488c7449feece410033f445d0b31/packages/adapter-drizzle/src/lib/mysql.ts#L356-L392","documentation":"updateAuthenticatorCounter looks up an authenticator (WebAuthn credential) by credentialID and throws this error when no row is returned. It cannot update the counter for a credential that is not registered in the authenticators table.","triggerScenarios":"adapter.updateAuthenticatorCounter(credentialID) with a credentialID that has no matching row — the authenticator was never registered via createAuthenticator, was deleted, or the credentialID doesn't match what was stored.","commonSituations":"WebAuthn login flow where the credential exists on the device but was never persisted (createAuthenticator skipped), wiping the database while keeping browser credentials, or multiple databases (register in one, authenticate against another).","solutions":["Ensure createAuthenticator was called during registration and the row committed before authentication.","Check the authenticators table contains the credentialID (SELECT manually).","Verify both registration and authentication flows use the same database/connection.","If the credential was deleted server-side, remove it client-side or re-register the passkey."],"exampleFix":"// before\nawait adapter.updateAuthenticatorCounter(credentialID)\n// after\nconst authenticator = await adapter.getAuthenticator(credentialID)\nif (!authenticator) throw new Error(`Credential ${credentialID} not registered`)\nawait adapter.updateAuthenticatorCounter(credentialID)","handlingStrategy":"validation","validationCode":"const authenticator = await adapter.getAuthenticator(credentialID)\nif (!authenticator) throw new Error(`Authenticator ${credentialID} is not registered`)","typeGuard":"function isRegisteredAuthenticator(a: AdapterAuthenticator | null): a is AdapterAuthenticator {\n  return a !== null && typeof a.credentialID === 'string'\n}","tryCatchPattern":"try {\n  await adapter.updateAuthenticatorCounter(credentialID)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Authenticator not found.') {\n    // treat as re-registration required; do not retry blindly\n  }\n  throw e\n}","preventionTips":["Always call createAuthenticator during WebAuthn registration before allowing logins","Keep registration and authentication on the same database","Purge client-side passkeys when server-side credentials are deleted","Verify credentialID values match exactly what was stored (no trimming/encoding drift)"],"tags":["database","webauthn","drizzle","record-not-found"],"backgroundTag":"record-not-found","analyzedSha":"a1a16a5a7780488c7449feece410033f445d0b31","analyzedAt":"2026-08-28T21:52:38.200Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}