Error message
NotAllowedError: The operation either timed out or was not allowed. See: https://www.w3.org/TR/webauthn-2/#sctn-privacy-considerations-client.
Also printed as
- NotAllowedError: The operation either timed out or was not allowed.
- NotAllowedError: CredentialsContainer request is not allowed.
Chromium's text is above (older versions omit the "See: …" link). Firefox says "CredentialsContainer request is not allowed." (reproduced in headless Firefox 157, which has no authenticator). The message differs per browser; only `e.name` is stable.
WebAuthn navigator.credentials.get() / create() — DOMException NotAllowedError (Chromium; Firefox wording in aliases)
What it means
The browser's catch-all WebAuthn failure. The specification deliberately makes "the user cancelled", "the timeout expired", "no authenticator has a matching credential" and "the request was not allowed in this context" indistinguishable to the web page, so a site cannot probe which credentials exist on a device (the linked privacy section explains why). Your code therefore has to treat it as "no credential was produced" and offer another path; the real cause is found by reproducing it, not by reading the error.
Why it happens
No credential from allowCredentials on this authenticator
commonThe account's passkey lives on another device, was deleted, or was registered under a different RP ID. The browser waits for a matching authenticator until the timeout and then reports NotAllowedError.
The user dismissed the dialog or the timeout expired
commonClosing the browser's passkey sheet, failing biometric verification too often, or a short `timeout` on a slow security-key flow all end the same way.
Called without a user gesture or from a hidden page
occasionalSafari in particular requires `create()`/`get()` to run in response to a click; calls after an `await` on a slow network request can lose the activation. Background tabs and cross-origin iframes without `publickey-credentials-*` permissions fail too.
No supported algorithm in pubKeyCredParams
occasionalIf the authenticator supports none of the COSE algorithms you list, registration fails with NotAllowedError rather than a specific error.
How to fix it
- 1.
Handle it as "no credential" and offer alternatives
Do not show a scary error. Offer another sign-in method, another device (hybrid/QR flow), or registration of a new passkey.
js try { const credential = await navigator.credentials.get({ publicKey: options }); await finishLogin(credential); } catch (e) { if (e.name === "NotAllowedError") { // Cancelled, timed out, or no passkey for this account on this device: offer alternatives. showOtherSignInOptions(); } else { throw e; } } - 2.
Offer common algorithms at registration
Listing ES256, EdDSA and RS256 covers practically all authenticators; your server must then verify all three.
js // Registration: offer the algorithms authenticators actually support. pubKeyCredParams: [ { type: "public-key", alg: -7 }, // ES256 { type: "public-key", alg: -8 }, // EdDSA (Ed25519) { type: "public-key", alg: -257 }, // RS256 (Windows Hello and older security keys) ],
Related errors
SecurityError: The relying party ID is not a registrable domain suffix of, nor…WebAuthn navigator.credentials.create() / get()InvalidStateError: The user attempted to register an authenticator that contain…WebAuthn navigator.credentials.create() with excludeCredentialsUnexpected registration response origin "http://localhost:3000", expected "http…SimpleWebAuthn (@simplewebauthn/server)