Error handling
The FIDO2 Web SDK uses a structured error handling system with categorized error codes to help you handle specific error scenarios effectively.
Error structure
All SDK errors are instances of Fido2WebSdkError, which extends the standard JavaScript Error class:
class Fido2WebSdkError extends Error {
name: 'Fido2WebSdkError'; // Error type identifier
code: string; // Unique error code (e.g. 'DBK-0005')
category: string; // Error category: 'DBK', 'VAL', 'CONV', or 'WEB'
shortDesc: string; // Brief description of the error type
details: string; // Detailed error message with context
message: string; // Full formatted message: '[CODE]: details'
}
Example error object:
{
name: 'Fido2WebSdkError',
code: 'DBK-0010',
category: 'DBK',
shortDesc: 'Failed to open IndexedDB',
details: 'IndexedDB is not available or blocked by browser settings',
message: '[DBK-0010]: IndexedDB is not available or blocked by browser settings'
}
To distinguish SDK errors from browser-native errors in your code:
if (error.name === 'Fido2WebSdkError') {
// Handle SDK-specific error
console.error(`SDK error [${error.code}]:`, error.details);
} else {
// Handle browser error (e.g. NotAllowedError, NotFoundError)
console.error('Browser error:', error.name, error.message);
}
Error categories
DBK errors — Device Bound Key
Category: DBK | Code range: DBK-0001 to DBK-0016
Errors related to Device Bound Key cryptographic operations and storage.
| Code | Constant | Short description | Common causes |
|---|---|---|---|
| DBK-0001 | DBK_INDEX_PRIVATE_KEY_NOT_FOUND |
Private key not found | HMAC seed missing from IndexedDB — call initSdk() first |
| DBK-0002 | DBK_INDEX_KEYPAIR_NOT_FOUND |
Keypair not found | DBK keypair missing from IndexedDB |
| DBK-0003 | DBK_INDEX_PUBLIC_KEY_RETRIEVAL_FAILED |
Failed to retrieve public key | Cryptographic key export failure |
| DBK-0004 | DBK_CRYPTO_KEY_GENERATION_FAILED |
Failed to generate key | Web Crypto key generation failure |
| DBK-0005 | DBK_CRYPTO_UNSUPPORTED_COSE_ALGORITHM |
Unsupported COSE algorithm | Algorithm not in supported list (ES256, ES384, ES512) |
| DBK-0006 | DBK_CRYPTO_UNSUPPORTED_DBK_ALGORITHM |
Unsupported DBK algorithm | Internal algorithm mapping failure |
| DBK-0007 | DBK_CRYPTO_INVALID_KEY_TYPE |
Expected EC key type | Non-EC key used where EC key is required |
| DBK-0008 | DBK_CRYPTO_UNSUPPORTED_ECDSA_CURVE |
Unsupported ECDSA curve | Key uses unsupported curve (not P-256/P-384/P-521) |
| DBK-0009 | DBK_CRYPTO_SIGNATURE_GENERATION_FAILED |
Failed to generate signature | ECDSA signing failure or invalid signature length |
| DBK-0010 | DBK_STORAGE_OPEN_FAILED |
Failed to open IndexedDB | IndexedDB not available, blocked, or quota exceeded |
| DBK-0011 | DBK_STORAGE_STORE_KEY_FAILED |
Failed to store key in IndexedDB | IndexedDB write failure or key already exists |
| DBK-0012 | DBK_STORAGE_LOAD_KEY_FAILED |
Failed to load key from IndexedDB | IndexedDB read failure; initSdk() not called |
| DBK-0013 | DBK_STORAGE_DELETE_KEY_FAILED |
Failed to delete key from IndexedDB | IndexedDB delete failure |
| DBK-0014 | DBK_STORAGE_STORE_KEYPAIR_FAILED |
Failed to store keypair in IndexedDB | IndexedDB write failure or keypair already exists |
| DBK-0015 | DBK_STORAGE_LOAD_KEYPAIR_FAILED |
Failed to load keypair from IndexedDB | User not registered with DBK on this browser |
| DBK-0016 | DBK_CRYPTO_NO_ACCEPTABLE_ALGORITHM |
No acceptable algorithm found | None of the server's allowedAlgorithms are accepted (client accepts: ES256, ES384, ES512) |
VAL errors — Validation
Category: VAL | Code range: VAL-0001 to VAL-0003
Input validation and parameter errors.
| Code | Constant | Short description | Common causes |
|---|---|---|---|
| VAL-0001 | VAL_FINAL_VALUE_INVALID |
Final value must not be undefined or null | A computed value is unexpectedly null or undefined |
| VAL-0002 | VAL_PARAMETER_REQUIRED |
Required parameter missing | Required parameter is null or undefined; or location.hostname is empty |
| VAL-0003 | VAL_INVALID_INPUT_TYPE |
Invalid input type | Input value cannot be decoded as the expected type (for example, invalid base64url) |
CONV errors — Conversion
Category: CONV | Code range: CONV-0001 to CONV-0011
Type conversion and format errors for WebAuthn API values.
| Code | Constant | Short description | Common causes |
|---|---|---|---|
| CONV-0001 | CONV_AUTHENTICATOR_ATTACHMENT_UNSUPPORTED |
Unsupported authenticator attachment type | Server returned unknown authenticatorAttachment value |
| CONV-0002 | CONV_ATTESTATION_ATTACHMENT_UNSUPPORTED |
Unsupported attestation attachment type | Server returned unknown attestation attachment value |
| CONV-0003 | CONV_ASSERTION_ATTACHMENT_UNSUPPORTED |
Unsupported assertion attachment type | Server returned unknown assertion attachment value |
| CONV-0004 | CONV_RESIDENT_KEY_REQUIREMENT_UNSUPPORTED |
Unsupported resident key requirement | Server returned unknown residentKey value |
| CONV-0005 | CONV_AUTHENTICATOR_TRANSPORT_UNSUPPORTED |
Unsupported authenticator transport | Server returned unknown transports value |
| CONV-0006 | CONV_ATTESTATION_CONVEYANCE_UNSUPPORTED |
Unsupported attestation conveyance preference | Server returned unknown attestation value |
| CONV-0007 | CONV_PUBLIC_KEY_CREDENTIAL_TYPE_UNSUPPORTED |
Unsupported public key credential type | Server returned credential type other than public-key |
| CONV-0008 | CONV_ATTESTATION_CREDENTIAL_TYPE_UNSUPPORTED |
Unsupported attestation credential type | Attestation response has unexpected credential type |
| CONV-0009 | CONV_ASSERTION_CREDENTIAL_TYPE_UNSUPPORTED |
Unsupported assertion credential type | Assertion response has unexpected credential type |
| CONV-0010 | CONV_AUTHENTICATOR_TRANSPORT_ARRAY_UNSUPPORTED |
Unsupported authenticator transport in array | Array contains unknown transport value |
| CONV-0011 | CONV_USER_VERIFICATION_REQUIREMENT_UNSUPPORTED |
Unsupported user verification requirement | Server returned unknown userVerification value |
WEB errors — WebAuthn
Category: WEB | Code range: WEB-0001 to WEB-0016
WebAuthn API operation errors.
| Code | Constant | Short description | Common causes |
|---|---|---|---|
| WEB-0001 | WEB_CREATE_OPTIONS_INVALID |
Invalid credential creation options | Malformed or missing required attestation options fields |
| WEB-0002 | WEB_CREATE_DBK_ALGORITHMS_EMPTY |
DBK allowedAlgorithms array is empty |
allowedAlgorithms present but empty in attestation options |
| WEB-0003 | WEB_CREATE_DBK_KEYPAIR_STORE_FAILED |
Failed to store DBK keypair | IndexedDB write failure during registration |
| WEB-0004 | WEB_CREATE_DBK_PUBLIC_KEY_EXPORT_FAILED |
Failed to export DBK public key | Web Crypto API export failure |
| WEB-0005 | WEB_CREATE_DBK_SIGN_FAILED |
Failed to sign with DBK | Signing operation failed during registration |
| WEB-0006 | WEB_CREATE_INVALID_CREDENTIAL_TYPE |
Invalid credential type in create response | WebAuthn returned unexpected credential type |
| WEB-0007 | WEB_GET_OPTIONS_INVALID |
Invalid credential get options | Malformed assertion options; rpId or version mismatch |
| WEB-0008 | WEB_GET_DBK_KEYPAIR_LOAD_FAILED |
Failed to load DBK keypair | DBK keypair not found or IndexedDB read failure |
| WEB-0009 | WEB_GET_DBK_SIGN_FAILED |
Failed to sign with DBK during assertion | Signing operation failed during authentication |
| WEB-0010 | WEB_GET_USERID_REQUIRED |
User ID is required for assertion | Authenticator did not return userHandle in userless flow |
| WEB-0011 | WEB_GET_INVALID_CREDENTIAL_TYPE |
Invalid credential type in get response | WebAuthn returned unexpected credential type |
| WEB-0012 | WEB_GET_AUTO_BINDING_NOT_PERMITTED |
Auto-binding not permitted | allowNewDbkBinding not set to true in assertion options |
| WEB-0013 | WEB_GET_ALLOWED_ALGORITHMS_REQUIRED |
allowedAlgorithms required |
Missing when allowNewDbkBinding is true |
| WEB-0014 | WEB_GET_ALLOWED_ALGORITHMS_EMPTY |
allowedAlgorithms must not be empty |
Empty array when allowNewDbkBinding is true |
| WEB-0015 | WEB_REGISTER_DUAL_REQUEST_REQUIRED |
Both assertionReq and attestationReq must be provided |
Missing one or both options in registerDeviceBoundCredential() |
| WEB-0016 | WEB_REGISTER_FALLBACK_CANCELLED |
User cancelled fallback to attestation | onFallbackConfirmation callback returned false |
Browser-native errors
In addition to SDK errors, the browser's WebAuthn API can throw its own errors:
| Error name | Description | Common causes |
|---|---|---|
NotAllowedError |
Operation not allowed | User cancelled, timeout, or no user gesture before the call |
NotSupportedError |
WebAuthn not supported | Browser does not support the WebAuthn API |
SecurityError |
Security requirements not met | Page not served over HTTPS; invalid origin |
InvalidStateError |
Invalid state | Authenticator already registered |
NotFoundError |
No matching credential | No credential found for the assertion |
AbortError |
Operation aborted | Cancelled by an AbortSignal |
ConstraintError |
Constraint not satisfied | Hardware or software constraint violation |
UnknownError |
Unknown error | General failure in the authenticator |
Error handling patterns
Handle errors by category
async function registerUser(attestationOptions) {
try {
const credential = await webauthnCreateCred({ options: attestationOptions });
return { success: true, credential };
} catch (error) {
if (error.name === 'Fido2WebSdkError') {
switch (error.category) {
case 'DBK':
return { success: false, errorType: 'device-key', message: error.shortDesc, code: error.code };
case 'WEB':
return { success: false, errorType: 'webauthn', message: error.shortDesc, code: error.code };
case 'VAL':
return { success: false, errorType: 'validation', message: error.shortDesc, code: error.code };
case 'CONV':
return { success: false, errorType: 'conversion', message: error.shortDesc, code: error.code };
default:
return { success: false, errorType: 'sdk', message: error.details, code: error.code };
}
} else {
// Browser-native errors
if (error.name === 'NotAllowedError') {
return { success: false, errorType: 'cancelled', message: 'Operation cancelled or timed out' };
}
if (error.name === 'InvalidStateError') {
return { success: false, errorType: 'already-registered', message: 'This authenticator is already registered' };
}
return { success: false, errorType: 'browser', message: error.message };
}
}
}
User-friendly error messages
function getUserFriendlyMessage(error) {
if (error.name === 'Fido2WebSdkError') {
switch (error.code) {
case 'DBK-0010':
return 'Browser storage is unavailable. Please check your browser settings.';
case 'DBK-0012':
return 'Authentication system not initialized. Please reload the page.';
case 'DBK-0015':
return 'No authentication key found for this device. Please register first.';
default:
return `Authentication error: ${error.shortDesc}`;
}
}
switch (error.name) {
case 'NotAllowedError':
return 'Operation was cancelled or timed out. Please try again.';
case 'NotSupportedError':
return 'Your browser does not support passwordless authentication.';
case 'SecurityError':
return 'Security requirements not met. Please use HTTPS.';
case 'InvalidStateError':
return 'This authenticator is already registered.';
case 'NotFoundError':
return 'No matching credentials found. Please register first.';
default:
return 'An unexpected error occurred. Please try again.';
}
}
Common error scenarios
SDK not initialized (DBK-0012)
Cause: initSdk() was not called before using other SDK functions.
Solution: Call initSdk() on page load and ensure it resolves before any other SDK operation.
window.addEventListener('load', async () => {
await initSdk();
});
IndexedDB not available (DBK-0010)
Causes: IndexedDB disabled in browser settings; storage quota exceeded; browser extension blocking storage.
Solution:
try {
await initSdk();
} catch (error) {
if (error.code === 'DBK-0010') {
showMessage('Browser storage is required. Please enable it in your browser settings.');
disableFido2Features();
}
}
Note
IndexedDB works in incognito or private browsing mode during the session, but data is cleared when the session ends. Inform users that Device Bound Keys are session-specific in incognito mode.
User cancelled (NotAllowedError)
Causes: User clicked Cancel on the authenticator prompt; operation timeout; no user gesture before the call.
Solution:
try {
const credential = await webauthnCreateCred({ options });
} catch (error) {
if (error.name === 'NotAllowedError') {
showMessage('Operation cancelled. Please try again when ready.');
enableRetryButton();
}
}
Authenticator already registered (InvalidStateError)
Cause: Attempting to register an authenticator that has already been registered.
Solution:
try {
const credential = await webauthnCreateCred({ options });
} catch (error) {
if (error.name === 'InvalidStateError') {
showMessage('This security key is already registered. Use it to sign in.');
showLoginButton();
}
}
No credentials found (NotFoundError)
Cause: No matching credentials during authentication.
Solution:
try {
const credential = await webauthnGetCred({ options });
} catch (error) {
if (error.name === 'NotFoundError') {
showMessage('No credentials found. Would you like to register?');
showRegistrationButton();
}
}
Device Bound Key not found (DBK-0015)
Cause: User attempting to authenticate with DBK but never registered on this device or browser, or IndexedDB was cleared.
Solution:
try {
const credential = await webauthnGetCred({ options });
} catch (error) {
if (error.code === 'DBK-0015') {
showMessage('No authentication key found for this device. Please register on this browser first.');
redirectToRegistration();
}
}
Auto-binding fallback suppressed (WEB-0016)
Cause: The SDK's default window.confirm() was silently suppressed by the browser (repeated calls, iframes, enterprise policy, headless environment). The SDK received false without any dialog being shown, and threw WEB-0016.
Solution: Always provide a custom onFallbackConfirmation callback in production:
const result = await registerDeviceBoundCredential({
assertionReq,
attestationReq,
onFallbackConfirmation: () => new Promise((resolve) => {
showMyModal({
message: 'Your passkey was not found on this browser. Register a new one?',
onConfirm: () => resolve(true),
onCancel: () => resolve(false),
});
}),
});
Error logging for support
When logging errors for support purposes, include the following context:
function logError(error, context) {
const log = {
timestamp: new Date().toISOString(),
context,
errorName: error.name,
errorMessage: error.message,
userAgent: navigator.userAgent,
url: window.location.href
};
if (error.name === 'Fido2WebSdkError') {
log.sdkError = {
code: error.code,
category: error.category,
shortDesc: error.shortDesc,
details: error.details
};
}
console.error('Error log:', log);
}
Related documentation
- API reference: Per-function error code listings
- Troubleshooting: Common issues and diagnostic steps
- Integration guide: Integration examples with error handling