braze-inc / braze-swift-sdk

Braze SDK for the Apple ecosystem, including: iOS, macOS, iPadOS, visionOS, tvOS
https://www.braze.com
Other
52 stars 19 forks source link

[Bug]: tvOS - App crash due to the cache size #34

Closed zijiaZ closed 1 year ago

zijiaZ commented 1 year ago

Platform

Other

Platform Version

tvOS 16.0

Braze SDK Version

5.8.0

Xcode Version

14.1

Computer Processor

Apple (M1)

Repro Rate

1%?

Steps To Reproduce

No steps, but once it hits the limit, it will crash the app every time upon launching

Expected Behavior

No crash? the AppboyPersistentData's size should not over 1M

Actual Incorrect Behavior

Crash the app

Verbose Logs

[User Defaults] CFPrefsPlistSource<0x600003673380> (Domain: com.XXXX.XXXXXX.dev, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: Yes): Attempting to store >= 1048576 bytes of data in CFPreferences/NSUserDefaults on this platform is invalid. This is a bug in XXXX-tvOS or a library it uses.
Description of keys being set:
AppboyPersistentData: data value, size: 1048451

Description of keys already present:
AppboyPersistentData: data value, size: 1048451
com.crashlytics.CLSUserDefaults.user-default-key.data-dictionary: dictionary value, count: 1, total nested objects: 2, approximate encoded size: 57
XXXXXX_uuid: string value, approximate encoded size: 36
userStatus: string value, approximate encoded size: 10
lastUpdateDate: date value
XXXX_auth_type: number value
XXXX_last_movie_viewed: string value, approximate encoded size: 6
XXXXusername: string value, approximate encoded size: 5
ABKLastSeenSDKVersion: string value, approximate encoded size: 5
hasShownLinearOnTVOS: boolean value
...
Total keys: 11 - Average approximate value size: 95326 bytes
NSUserDefaults/CFPreferences byte count limit reached for com.XXXX.XXXXXX.dev
_LSContextInitReturningError() failed with error Error Domain=NSOSStatusErrorDomain Code=-10817 "(null)" UserInfo={_LSFunction=_LSSchemaConfigureForStore, ExpectedSimulatorHash={length = 32, bytes = 0xb37e8d26 b7af697a e09dff08 8225461b ... 42f623a1 c4e387e8 }, _LSLine=478, WrongSimulatorHash={length = 32, bytes = 0xf9b0ff98 e7c1e533 a9e74312 efc154db ... dde6b6d4 9c340050 }}
CoreSimulator 857.13 - Device: Apple TV 4K (at 1080p) (2nd generation) (6B7F50B8-7E89-4B75-8094-008793CD2EBF) - Runtime: tvOS 16.0 (20J373) - DeviceType: Apple TV 4K (2nd generation) (at 1080p)

Additional Information

No response

lowip commented 1 year ago

Hi @zijiaZ,

The Swift SDK only deletes the AppboyPersistentData key in the user defaults. It never writes to that key. Can you confirm that the crashes are coming from versions of your app integrating the Swift SDK and not our ObjC SDK (Appboy-tvOS-SDK)?

The Swift SDK has safeguards to avoid this exact crash. See the tvOSPersistedSizeLimit configuration.

zijiaZ commented 1 year ago

Hi @lowip We used the Appboy-tvOS-SDK before and just updated to the Swift SDK recently, but we are seeing the crash on both version. Our latest app using the Swift SDK, also reporting the crash.. hope it helps

Screen Shot 2023-01-17 at 4 16 59 PM

lowip commented 1 year ago

Hi @zijiaZ,

We have released 5.9.0 which includes a tentative fix. Please let us know if you still see this error.

zijiaZ commented 1 year ago

5.9.0

TYVM, Will let you know!

hokstuff commented 1 year ago

Hi @zijiaZ, are you still experiencing this issue after testing with 5.9.0?

zijiaZ commented 1 year ago

Hi @zijiaZ, are you still experiencing this issue after testing with 5.9.0?

Hey @hokstuff , we would not know until late next week

zijiaZ commented 1 year ago

@hokstuff @lowip We are still seeing the crash after integrating 5.9.0

lowip commented 1 year ago

Hi @zijiaZ,

Could you send us one of the latest crash logs? The last screenshot doesn't contain any Braze / Appboy related symbols.

zijiaZ commented 1 year ago

here is a newer one, basically the same with older one. Complaining about storing too much data

Screenshot 2023-03-07 at 2 59 59 PM

I reproduced it once a few month ago on xcode the the logs on console mentioned AppboyPersistentData (More details on Verbose Logs above):

[User Defaults] CFPrefsPlistSource<0x600003673380> (Domain: com.XXXX.XXXXXX.dev, User: kCFPreferencesCurrentUser, ByHost: No, Container: (null), Contents Need Refresh: Yes): Attempting to store >= 1048576 bytes of data in CFPreferences/NSUserDefaults on this platform is invalid. This is a bug in XXXX-tvOS or a library it uses.
Description of keys being set:
AppboyPersistentData: data value, size: 1048451`

So I suspect it might be related to the Braze SDK

lowip commented 1 year ago

Hi @zijiaZ,

Thanks for the new screenshot. As you mentioned, it doesn't provide much more information and no clear link to Appboy / Braze.

On tvOS (device only), the maximum allowed size for UserDefaults.standard is 1 MB. Past that limit, the system will throw an exception, as pictured in the provided stack traces. UserDefaults.standard being a shared store, the Appboy / Braze SDK data lives side-by-side with your own application data. So both Braze's and your own usage of UserDefaults.standard can lead to the exception, depending on how close to the limit the current device is.

The specific error you saw a few months back where the SDK tries to write 1048451 bytes (1 MB+) can only happen in the Appboy SDK. The Swift SDK does not try to write AppboyPersistentData, it simply deletes it as part of a migration cleanup step.

The fact that you're experiencing this error means that the user has a very large number of campaigns (NewsFeed, Content Cards or In-App Messages) for which the total size exceeds 1 MB. The Appboy SDK does not provide safeguards against that use-case, and you might have started to see this crash more frequently if more campaigns have been created targeting the impacted users.

This is an issue that we identified while developing our Swift SDK. We now minimize the risk of such crash by:

Hopefully this sheds some light on the situation. My recommendation is to upgrade to the Swift SDK to benefit from these improvements. I would also advise you to analyze your own usage of UserDefaults.standard on tvOS to ensure that you don't go mistakenly past that 1 MB limit.

I'm closing the issue, as there's nothing else we can do on the Swift SDK side to minimize further our persisted data footprint.