nextauthjs/next-auth · error

Verification Token not used

Error message

Verification Token not used

What it means

useVerificationToken() consumes (reads and deletes) a verification token during sign-in. If anything in the try block throws — connection error, query failure, unexpected doc shape — the empty catch converts it into 'Verification Token not used'. A genuinely absent token returns null instead, so this error usually means an operation failed rather than a missing token.

Source

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

        const [tokens] = await surreal.query<[VerificationTokenDoc[]]>(
          `SELECT * FROM verification_token WHERE identifier = $identifier AND token = $vt LIMIT 1`,
          { identifier, vt: token }
        )
        if (tokens.length && tokens.at(0)) {
          const vt = tokens[0]
          if (vt) {
            await surreal.delete(vt.id)
            const verificationTokenDoc: Partial<VerificationTokenDoc> = vt
            if (verificationTokenDoc.id) delete verificationTokenDoc.id
            return docToVerificationToken(
              verificationTokenDoc as VerificationTokenDoc
            )
          }
        } else {
          return null
        }
      } catch {}
      throw new Error("Verification Token not used")
    },
    async getAccount(
      providerAccountId: AdapterAccount["providerAccountId"],
      provider: AdapterAccount["provider"]
    ) {
      const surreal = await client
      try {
        const [accountsDoc] = await surreal.query<[AccountDoc[]]>(
          `SELECT * FROM account WHERE providerAccountId = $pid AND provider = $provider LIMIT 1`,
          {
            pid: providerAccountId,
            provider,
          }
        )
        if (accountsDoc.length) {
          return docToAccount(accountsDoc[0])
        }
      } catch {}

View on GitHub (pinned to a1a16a5a77)

Solutions

  1. Retry the sign-in flow; if intermittent, check SurrealDB availability/logs at that moment
  2. Verify the stored token doc matches the expected VerificationTokenDoc shape (identifier, token, expires)
  3. Check SurrealDB permissions allow SELECT and DELETE on the token table
  4. Add logging in the try block to surface the swallowed error
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const token = await adapter.useVerificationToken({ identifier, token })
  if (token === null) {
    // genuinely missing/expired token — show 'invalid link' UI
  }
  return token
} catch (e) {
  // 'Verification Token not used' => DB/query failure, not a bad token
  console.error('useVerificationToken DB failure', e)
  throw e
}

Prevention

When it happens

Trigger: SurrealDB transaction/query for fetching+deleting the token threw; the returned doc could not be converted by docToVerificationToken; database unreachable at sign-in time.

Common situations: User clicks a magic link while the DB is briefly unavailable; schema change made the stored doc incompatible with VerificationTokenDoc; permissions deny DELETE on the token table.

Related errors


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