QuantumNous/new-api · info · Error

Passkey verification was cancelled

Error message

Passkey verification was cancelled

What it means

Thrown in verifyPasskey() when navigator.credentials.get() resolves to null instead of throwing. Per the WebAuthn spec the promise can resolve null when no credential is produced, which in practice corresponds to the user dismissing or aborting the picker without a DOMException. It is a user-abort condition, not a system failure.

Source

Thrown at web/src/features/auth/secure-verification/api.ts:157

      throw new Error(
        beginResponse.message || i18next.t('Failed to start verification')
      )
    }

    const publicKey = prepareCredentialRequestOptions(
      beginResponse.data?.options ?? beginResponse.data
    )
    const flowToken = beginResponse.data?.flow_token
    if (!flowToken) {
      throw new Error(i18next.t('Verification flow expired'))
    }

    const credential = (await navigator.credentials.get({
      publicKey,
    })) as PublicKeyCredential | null

    if (!credential) {
      throw new Error(i18next.t('Passkey verification was cancelled'))
    }

    const assertion = buildAssertionResult(credential)
    if (!assertion) {
      throw new Error(i18next.t('Unable to build Passkey assertion'))
    }

    const finishResponse = await finishPasskeyVerification(flowToken, assertion)
    if (!finishResponse.success) {
      throw new Error(
        finishResponse.message || i18next.t('Passkey verification failed')
      )
    }

    if (!finishResponse.data?.proof_token) {
      throw new Error(i18next.t('Verification proof was not returned'))
    }
    return finishResponse.data

View on GitHub (pinned to e2c7aa7b10)

Solutions

  1. Treat this as user cancellation: return the user to the verification choice instead of showing an error.
  2. Offer the 2FA code method as an alternative after cancellation.
  3. No system fix is needed unless it fires without user action — then check for malformed publicKey options (bad rpId, empty allowList, invalid challenge).

Example fix

// before
catch (e) { toast.error(getErrorMessage(e)) }

// after — classify cancellation as non-error
try {
  await verify('passkey', scope)
} catch (e) {
  if (/cancelled/i.test(getErrorMessage(e))) {
    return // user aborted, back to method selection
  }
  toast.error(getErrorMessage(e))
}
Defensive patterns

Strategy: try-catch

Try / catch

try {
  await verify('passkey', scope)
} catch (e) {
  if (/cancelled/i.test(getErrorMessage(e))) return // silent user abort
  toast.error(getErrorMessage(e))
}

Prevention

When it happens

Trigger: User cancels the browser's passkey/authenticator selection dialog in a way that resolves null; browser quirk where dismissal resolves instead of rejecting with NotAllowedError.

Common situations: User closes the OS-level WebAuthn sheet; user presses Escape on some platforms; conditional-mediation autofill dismissed.

Related errors


AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15). Data as JSON: /api/errors/bda6974f3cbe6815. Report an issue: GitHub.