From f4fe13b8fe4e99e571b4afa5b2df0a87773d4ef8 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Tue, 6 Jan 2026 15:59:19 -0800 Subject: [PATCH 1/4] [FCM] Narrower database open recovery logic --- .../Sources/FIRMessagingRmqManager.m | 55 ++++++++++++------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m index ed01c0ad26f..5939f5bd1a6 100644 --- a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m +++ b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m @@ -530,31 +530,46 @@ - (void)openDatabase { // If opening the database failed, it might be corrupt. Try to recover by deleting and // recreating it. if (result != SQLITE_OK) { - FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, - @"Could not open RMQ database at path: %@. " - "Will delete and try to recreate it.", - path); - NSError *removeError; - if (![[NSFileManager defaultManager] removeItemAtPath:path error:&removeError]) { - FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, - @"Failed to delete corrupt database at %@: %@", path, removeError); - } - // After deleting, try to open it again. - result = sqlite3_open_v2([path UTF8String], &self->_database, flags, NULL); - // If it still fails after the recovery attempt, then assert and crash. - if (result != SQLITE_OK) { + if (result == SQLITE_CANTOPEN) { + FIRMessagingLoggerWarn( + kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, + @"Could not open RMQ database at path: %@. Will delete and try to recreate it.", + path); + NSError *removeError; + if (![[NSFileManager defaultManager] removeItemAtPath:path error:&removeError]) { + FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, + @"Failed to delete corrupt database at %@: %@", path, + removeError); + } + // After deleting, try to open it again. + result = sqlite3_open_v2([path UTF8String], &self->_database, flags, NULL); + // If it still fails after the recovery attempt, then assert and crash. + if (result != SQLITE_OK) { + NSString *errorString = FIRMessagingStringFromSQLiteResult(result); + NSString *errorMessage = [NSString + stringWithFormat:@"Could not open or create RMQ database at path %@, error: %@", + path, errorString]; + FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, + @"%@", errorMessage); + NSAssert(NO, errorMessage); + didOpenDatabase = NO; // Still failed, so indicate database did not open. + } else { + // Successfully recreated after corruption, so treat as a new database for table + // creation. + didOpenDatabase = YES; // Indicate successful opening after recreation. + [self createTable]; + } + } else { NSString *errorString = FIRMessagingStringFromSQLiteResult(result); - NSString *errorMessage = [NSString - stringWithFormat:@"Could not open or create RMQ database at path %@, error: %@", path, - errorString]; + NSString *errorMessage = + [NSString stringWithFormat: + @"Could not open RMQ database at path %@, error: %@. Won't delete the " + "database as it is not a corrupt database error.", + path, errorString]; FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, @"%@", errorMessage); NSAssert(NO, errorMessage); didOpenDatabase = NO; // Still failed, so indicate database did not open. - } else { - // Successfully recreated after corruption, so treat as a new database for table creation. - didOpenDatabase = YES; // Indicate successful opening after recreation. - [self createTable]; } } else { [self updateDBWithStringRmqID]; From 1b7b03099f8046a56a112a9fea511ae765b89eee Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Tue, 6 Jan 2026 16:03:11 -0800 Subject: [PATCH 2/4] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- FirebaseMessaging/Sources/FIRMessagingRmqManager.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m index 5939f5bd1a6..f0e4b17267b 100644 --- a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m +++ b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m @@ -538,7 +538,7 @@ - (void)openDatabase { NSError *removeError; if (![[NSFileManager defaultManager] removeItemAtPath:path error:&removeError]) { FIRMessagingLoggerWarn(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, - @"Failed to delete corrupt database at %@: %@", path, + @"Failed to delete database for recovery at %@: %@", path, removeError); } // After deleting, try to open it again. @@ -554,7 +554,7 @@ - (void)openDatabase { NSAssert(NO, errorMessage); didOpenDatabase = NO; // Still failed, so indicate database did not open. } else { - // Successfully recreated after corruption, so treat as a new database for table + // Successfully recreated after an open failure, so treat as a new database for table // creation. didOpenDatabase = YES; // Indicate successful opening after recreation. [self createTable]; From 9ed48d9c8e00273fd11cbc87d94cd27c2345e8f9 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Tue, 6 Jan 2026 16:07:44 -0800 Subject: [PATCH 3/4] Apply suggestions from code review Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- .../Sources/FIRMessagingRmqManager.m | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m index f0e4b17267b..de7539bcde9 100644 --- a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m +++ b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m @@ -546,9 +546,9 @@ - (void)openDatabase { // If it still fails after the recovery attempt, then assert and crash. if (result != SQLITE_OK) { NSString *errorString = FIRMessagingStringFromSQLiteResult(result); - NSString *errorMessage = [NSString - stringWithFormat:@"Could not open or create RMQ database at path %@, error: %@", - path, errorString]; + NSString *errorMessage = [NSString stringWithFormat: + @"Could not open or create RMQ database at path %@, error: %@", + path, errorString]; FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, @"%@", errorMessage); NSAssert(NO, errorMessage); @@ -561,11 +561,10 @@ - (void)openDatabase { } } else { NSString *errorString = FIRMessagingStringFromSQLiteResult(result); - NSString *errorMessage = - [NSString stringWithFormat: - @"Could not open RMQ database at path %@, error: %@. Won't delete the " - "database as it is not a corrupt database error.", - path, errorString]; + NSString *errorMessage = [NSString stringWithFormat: + @"Could not open RMQ database at path %@, error: %@. Won't delete the " + @"database as it is not a corrupt database error.", + path, errorString]; FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, @"%@", errorMessage); NSAssert(NO, errorMessage); From 19edf473dccf6d1ba5d4dea3d5d341734b5a4394 Mon Sep 17 00:00:00 2001 From: Paul Beusterien Date: Tue, 6 Jan 2026 16:11:22 -0800 Subject: [PATCH 4/4] style --- .../Sources/FIRMessagingRmqManager.m | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m index de7539bcde9..a21ce8506ef 100644 --- a/FirebaseMessaging/Sources/FIRMessagingRmqManager.m +++ b/FirebaseMessaging/Sources/FIRMessagingRmqManager.m @@ -546,9 +546,9 @@ - (void)openDatabase { // If it still fails after the recovery attempt, then assert and crash. if (result != SQLITE_OK) { NSString *errorString = FIRMessagingStringFromSQLiteResult(result); - NSString *errorMessage = [NSString stringWithFormat: - @"Could not open or create RMQ database at path %@, error: %@", - path, errorString]; + NSString *errorMessage = [NSString + stringWithFormat:@"Could not open or create RMQ database at path %@, error: %@", + path, errorString]; FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, @"%@", errorMessage); NSAssert(NO, errorMessage); @@ -561,10 +561,11 @@ - (void)openDatabase { } } else { NSString *errorString = FIRMessagingStringFromSQLiteResult(result); - NSString *errorMessage = [NSString stringWithFormat: - @"Could not open RMQ database at path %@, error: %@. Won't delete the " - @"database as it is not a corrupt database error.", - path, errorString]; + NSString *errorMessage = + [NSString stringWithFormat: + @"Could not open RMQ database at path %@, error: %@. Won't delete the " + @"database as it is not a corrupt database error.", + path, errorString]; FIRMessagingLoggerError(kFIRMessagingMessageCodeRmq2PersistentStoreErrorOpeningDatabase, @"%@", errorMessage); NSAssert(NO, errorMessage);