nextauthjs/next-auth · error

Authenticator not created

Error message

Authenticator not created

What it means

createAuthenticator() persists a WebAuthn/passkey authenticator. If the SurrealDB create throws or returns an empty array, the adapter throws 'Authenticator not created', discarding the root cause in an empty catch.

Source

Thrown at packages/adapter-surrealdb/src/index.ts:503

        )
        if (accountsDoc.length) {
          return docToAccount(accountsDoc[0])
        }
      } catch {}
      return null
    },
    async createAuthenticator(authenticator: AdapterAuthenticator) {
      try {
        const surreal = await client
        const authenticatorDoc = await surreal.create<
          AuthenticatorDoc,
          Omit<AuthenticatorDoc, "id">
        >("authenticator", authenticatorToDoc(authenticator))
        if (authenticatorDoc.length) {
          return docToAuthenticator(authenticatorDoc[0])
        }
      } catch {}
      throw new Error("Authenticator not created")
    },
    async getAuthenticator(credentialId: AdapterAuthenticator["credentialID"]) {
      const surreal = await client
      try {
        const [authenticatorDoc] = await surreal.query<[AuthenticatorDoc[]]>(
          `SELECT * FROM authenticator WHERE credentialID = $cid LIMIT 1`,
          {
            cid: credentialId,
          }
        )
        if (authenticatorDoc.length) {
          return docToAuthenticator(authenticatorDoc[0])
        }
      } catch {}
      return null
    },
    async listAuthenticatorsByUserId(userId: AdapterAuthenticator["userId"]) {
      const surreal = await client

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Verify SurrealDB is reachable and the `authenticator` table exists and is writable
  2. Check permissions allow CREATE on the authenticator table for the adapter user
  3. Ensure the WebAuthn credential payload (credentialID, publicKey, counter) is complete before the call
  4. Add temporary logging inside the try to expose the underlying error
Defensive patterns

Strategy: validation

Validate before calling

if (!authenticator?.credentialID || !authenticator?.credentialPublicKey) {
  throw new Error('Authenticator payload missing credentialID/publicKey')
}
await adapter.createAuthenticator(authenticator)

Type guard

function isValidAuthenticator(a: AdapterAuthenticator): boolean {
  return typeof a.credentialID === 'string' && a.credentialID.length > 0 &&
    a.credentialPublicKey != null && typeof a.userId === 'string'
}

Try / catch

try {
  return await adapter.createAuthenticator(authenticator)
} catch (e) {
  if (e.message === 'Authenticator not created') {
    console.error('WebAuthn authenticator insert failed — check SurrealDB', e)
  }
  throw e
}

Prevention

When it happens

Trigger: surreal.create('authenticator', ...) fails (connectivity, permissions, schema) or yields zero rows; authenticatorToDoc produced invalid fields (e.g. credentialID/credentialPublicKey malformed).

Common situations: Passkey registration failing because the authenticator table lacks CREATE permission; SurrealDB misconfigured namespace/database; duplicate credentialID being inserted.

Understand the failure class

Related errors


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