laurent22/joplin · error · Error
Could not verify your identity: %s
Error message
Could not verify your identity: %s
What it means
Thrown by `biometricAuthenticate` when the underlying biometric API rejects the authentication attempt. The `%s` placeholder is filled with `errorName` from the OS biometrics call. The earlier branch that handles 'biometric unlock not setup' returns early; reaching this throw means a biometric prompt was shown and failed (e.g. no match, user cancelled, hardware error).
Source
Thrown at packages/app-mobile/components/biometrics/biometricAuthenticate.ts:26
logger.info('Authenticate...');
const result = await authenticateAsync({ promptMessage: _('Verify your identity') });
if (result.success === false) {
const errorName = result.error;
if (errorName === 'not_enrolled' || errorName === 'not_available') {
// In that case we skip the check because the device biometric unlock has been disabled
// by the user. It should be safe to skip the check since in order to disable it, they
// must have full access to the phone, and should have to enter their pin. Not skipping
// the check would be a problem if biometric unlock was disabled as a result of being
// broken. In this case, the user will never be able to unlock Joplin.
// Ref: https://github.com/laurent22/joplin/issues/10926
logger.warn('Biometric unlock is not setup on the device - skipping check');
return;
// errorMessage = _('Biometric unlock is not setup on the device. Please set it up in order to unlock Joplin. If the device is on lockout, consider switching it off and on to reset biometrics scanning.');
}
throw new Error(_('Could not verify your identity: %s', errorName));
}
logger.info('Authenticate done');
};
View on GitHub (pinned to 2654b33620)
Solutions
- Catch the error and offer the fallback unlock path (master password / PIN).
- Detect a 'user cancelled' errorName and silently return rather than surfacing it as a hard failure.
- If errorName indicates lockout, inform the user to wait or restart the device to reset the sensor (ref #10926).
- Ensure biometrics are actually enrolled on the device before prompting.
Example fix
// before
await biometricAuthenticate();
// after
try {
await biometricAuthenticate();
} catch (error) {
if (/cancelled/i.test(error.message)) return;
await showFallbackPasswordUnlock();
} Defensive patterns
Strategy: fallback
Validate before calling
null
Type guard
null
Try / catch
try {
await biometricAuthenticate();
} catch (error) {
const msg = error.message || '';
if (/cancelled/i.test(msg)) return; // user-initiated cancel
if (/lockout/i.test(msg)) {
await showLockoutGuidance();
}
await fallbackToPasswordUnlock();
} Prevention
- Always provide a non-biometric fallback unlock path.
- Detect cancellation errors and treat them as a no-op rather than a failure.
- Check that biometrics are enrolled before prompting.
When it happens
Trigger: User submits a fingerprint/face that is not enrolled, cancels the prompt, or the sensor times out / lockout after too many failed attempts. Any non-recoverable failure from the native biometrics API after the 'not setup' early-return has been skipped.
Common situations: Wrong finger presented; face unlock obscured; biometric sensor hardware fault; device policy enforcing biometric lockout after repeated failures; the user dismissed the system prompt.
Related errors
- Authentication failed! ${error}
- Cannot initialise synchroniser.
- Locked notes cannot be opened in an external editor
- Item not found: ${itemId}
- Unsupported item type for links: ${item.type_}
AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12).
Data as JSON: /api/errors/427c4ad018df32b6.
Report an issue: GitHub.