QuantumNous/new-api · info · Error
Passkey verification was cancelled or timed out
Error message
Passkey verification was cancelled or timed out
What it means
Thrown from the catch in verifyPasskey() when navigator.credentials.get() rejects with a DOMException named NotAllowedError. Per the WebAuthn spec this is the standard signal that the user declined the browser prompt or the operation timed out waiting for user consent. The original exception is preserved via { cause: error } for diagnostics.
Source
Thrown at web/src/features/auth/secure-verification/api.ts:178
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
} catch (error: unknown) {
if (error instanceof DOMException && error.name === 'NotAllowedError') {
throw new Error(
i18next.t('Passkey verification was cancelled or timed out'),
{ cause: error }
)
}
if (error instanceof DOMException && error.name === 'InvalidStateError') {
throw new Error(
i18next.t('Passkey verification is not available in the current state'),
{ cause: error }
)
}
throw error
}
}
View on GitHub (pinned to e2c7aa7b10)
Solutions
- No system fix: this is expected user behaviour — route the user back to method selection (e.g. offer the 2FA code).
- Show a neutral 'cancelled' message rather than an error-styled toast.
- If it fires without any prompt appearing, check that only one credentials.get() runs at a time (concurrent calls are aborted with NotAllowedError).
Defensive patterns
Strategy: try-catch
Type guard
const isUserCancellation = (e: unknown): boolean => (e instanceof Error && /cancelled/i.test(e.message)) || (e instanceof DOMException && e.name === 'NotAllowedError')
Try / catch
try {
await verify('passkey', scope)
} catch (e) {
if (isUserCancellation(e)) {
returnToMethodSelection() // silent, no error toast
}
toast.error(getErrorMessage(e))
} Prevention
- Classify NotAllowedError as cancellation and never show it as a failure
- Offer the 2FA fallback after cancellation so users are not stuck
- Avoid launching two credentials.get() ceremonies concurrently
When it happens
Trigger: User clicks 'Cancel' on the browser/OS passkey prompt; user does not interact with the prompt before the browser's timeout (commonly ~30-120s); user denies the subsequent biometric/OS authentication step.
Common situations: Everyday user cancellation during security-sensitive operations (delete token, change password); user walks away from the machine; touch/face ID fails repeatedly then aborts.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Passkey verification was cancelled
- Passkey verification is not available in the current state
- Passkey verification is not supported in this environment
- Failed to start verification
- Verification flow expired
AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15).
Data as JSON: /api/errors/9665bf97ecc7a27b.
Report an issue: GitHub.