WebAuthn and FIDO2 surface failures as DOMException objects whose name property tells you what
went wrong. This reference lists the names thrown by navigator.credentials.create() and
navigator.credentials.get(), what triggers each, and a clear message to show the user.
How it works
A WebAuthn ceremony returns a rejected promise on failure. You inspect the rejection’s name:
try {
const cred = await navigator.credentials.get({ publicKey });
} catch (err) {
if (err.name === "NotAllowedError") {
// user cancelled, timed out, or no credential matched
}
}
The platform intentionally limits how much detail it exposes. Most user-driven failures and
timeouts collapse into a single NotAllowedError so that a website cannot fingerprint which
authenticators or passkeys a person has. The errors you can distinguish are mostly developer
mistakes — a wrong rp.id, an insecure context, an already-registered key, or an algorithm the
authenticator does not support.
Notes and examples
InvalidStateErrorduring registration is not a bug — it meansexcludeCredentialsmatched an existing credential, i.e. the user is already enrolled. Treat it as “already registered”.SecurityErroralmost always means your relying party ID does not match the origin, or the page is not a secure context.- Never display a raw
DOMExceptionstring. Map the name to one of the user messages below. - Because cancel and timeout both produce
NotAllowedError, always provide a retry path rather than a dead end.