Keychain operations can fail for various reasons: incorrect accessibility settings, missing items, device lock state, or invalid parameters. Proper error handling ensures your app responds gracefully to these situations.
Most errors come from Apple’s Security framework (defined in SecBase.h). These are returned with the OSStatus type:
errSecSuccess (0)
Meaning: Operation completed successfully
if (error.code == errSecSuccess || error == nil) { // Success - no error occurred}
When successful, the error parameter is typically nil, but checking for errSecSuccess is also valid.
errSecItemNotFound (-25300)
Meaning: The keychain item does not existCommon causes:
Attempting to fetch a password that was never saved
Wrong service or account name
Item was already deleted
Handling Item Not Found
NSError *error = nil;NSString *password = [SAMKeychain passwordForService:@"com.myapp.MyApp" account:@"user@example.com" error:&error];if (error.code == errSecItemNotFound) { NSLog(@"No password found for this account"); // This is often not an error - just means user hasn't logged in yet}
This is often expected behavior (e.g., on first launch) and doesn’t always indicate a problem.
errSecDuplicateItem (-25299)
Meaning: An item with the same service and account already existsWhen this occurs:
Manually adding items with Security framework APIs
Race conditions in multi-threaded code
Handling Duplicates
if (error.code == errSecDuplicateItem) { NSLog(@"Item already exists"); // SAMKeychain normally handles this automatically by updating // If you see this, it may indicate an unusual condition}
SAMKeychain automatically handles duplicates by updating existing items, so you should rarely see this error.
errSecInteractionNotAllowed (-25308)
Meaning: User interaction is required but not possibleCommon causes:
Device is locked and item requires device unlock
Accessibility setting prevents access in current state
Background operation attempting to access protected item
Handling Interaction Not Allowed
NSError *error = nil;NSString *password = [SAMKeychain passwordForService:@"com.myapp.MyApp" account:@"user@example.com" error:&error];if (error.code == errSecInteractionNotAllowed) { NSLog(@"Cannot access keychain item - device may be locked"); // Retry when device is unlocked or app is in foreground}
This often indicates an accessibility mismatch. Review your accessibility settings (see Accessibility).
errSecAuthFailed (-25293)
Meaning: Authentication or authorization failedCommon causes:
User denied access to keychain item
Insufficient privileges
Access control restrictions
Handling Auth Failed
if (error.code == errSecAuthFailed) { NSLog(@"Authorization failed"); // User may have denied access or security policy prevents access}
errSecParam (-50)
Meaning: One or more parameters passed to the function were invalid
if (error.code == errSecParam) { NSLog(@"Invalid parameter"); // Check all parameters for correctness}
errSecUnimplemented (-4)
Meaning: Function or operation not implemented
if (error.code == errSecUnimplemented) { NSLog(@"Operation not implemented on this platform");}
errSecNotAvailable (-25291)
Meaning: No keychain is availableCommon causes:
Keychain access not configured in provisioning profile
Simulator issues
Corrupted keychain
if (error.code == errSecNotAvailable) { NSLog(@"Keychain is not available"); // Check provisioning profile and entitlements}
errSecAllocate (-108)
Meaning: Memory allocation failure
if (error.code == errSecAllocate) { NSLog(@"Memory allocation failed"); // Severe system error - very rare}
errSecDecode (-26275)
Meaning: Unable to decode the provided data
if (error.code == errSecDecode) { NSLog(@"Failed to decode keychain data"); // Data may be corrupted}