realm / realm-swift

Realm is a mobile database: a replacement for Core Data & SQLite
https://realm.io
Apache License 2.0
16.29k stars 2.14k forks source link

Realm Migration Error #8105

Closed tejuamirthi closed 1 year ago

tejuamirthi commented 1 year ago

How frequently does the bug occur?

Sometimes

Description

Hey,

We are facing an issue using RealmSwift during a migration. The migration fails even after following the below steps:

It is happening 6/10 times and we are facing this issue in production with some users stuck on this error.

Here's a sample project link with our requirements where we were able to reproduce the issue. Please do pod install before proceeding further.

Highly appreciate any help. Thanks!

Stacktrace & log output

RealmTest: Realm init error during migration Error Domain=io.realm Code=10 "Migration is required due to the following errors:
- Property 'CarObject.newProperty21' has been removed.
- Property 'CarObject.newProperty25' has been added." UserInfo={NSLocalizedDescription=Migration is required due to the following errors:
- Property 'CarObject.newProperty21' has been removed.
- Property 'CarObject.newProperty25' has been added., Error Code=10}

Can you reproduce the bug?

Always

Reproduction Steps

Please refer RealmManager.swift in the sample project shared for following the below steps and for more suggestions.

STEP 1: Uncomment the following lines and run the main app // TestCar().testCarMethod(realm: realm) // safeWriteManyRecords(realm: realm)

STEP 2: Comment the above lines and stop the app

STEP 3: Select Widget extension scheme and run the extension on the same simulator/device you were running the main app.

STEP 4: Select Main app scheme, trigger the migration by updating realm objects(search for STEP 4 in codebase for easy suggestions)

STEP 5: Update the realm schema version and run the main app in the same sim/device. You can observe the schema version is updated to new schema version even before the config is set which might be preventing the migration to happen.

STEP 6: If the above steps doesn't reproduce the issue please erase the simulator(if using device, delete the app), follow STEP 1 - STEP 5 again. It should be reproducible in next two times.

Version

10.15.1, also observed in 10.33.0

What Atlas Services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

iOS 12-16

Build environment

Xcode version: 14.2 Dependency manager and version: Cocoapods 1.11.3

leemaguire commented 1 year ago

Hi @tejuamirthi Thanks for providing us with a reproduction app. I could not reproduce your issue with the attached app unfortunately even following your steps.

My thinking is that something is just out of sync/stale and when such scenario happens you just need to delete the app from the simulator/device during development. I did notice that the reason the newVersion var was bumped before the migration ran is because the Widget performed the migration first. Widgets are known to be hard to debug as it is not easy to attach the debugger at the point of init(), but it is definitely not a compiler issue as you suspected.

tejuamirthi commented 1 year ago

Thank you for checking this out. We were able to reproduce this more often. Glad to help you reproduce if needed.

It makes sense for the version bump to be updated already if migration is performed from Widgets. Is there a way to confirm this apart from attaching debugger?

We were not able to reproduce the issue if we triggered the migration in a background thread(different queue - code below) but we didn't understand why it worked. Please do let us know if you have any info on those lines too. Background thread code block for triggering migration(should be done along with bump in schema version):

queue.async {
  Realm.Configuration.defaultConfiguration = config

  do {
    let realm = try Realm()
    print("RealmTest: Realm init success in different queue")
  } catch {
    print("RealmTest: Realm init error during migration within queue")
  }
}

Also can you please share any recommended ways to do Realm migration involving widget extensions?

leemaguire commented 1 year ago

Would you be able to create an app that reproduces 100% of the time? You could utilise console logging with the os_log. I don't see any reason why opening the realm in a queue would make a difference. A migration should perform no different in a widget then in an app. Out of curiosity, do you only see this problem with CarObject? Or is it an issue on any type of Realm Object that has been modified?

tejuamirthi commented 1 year ago

Thanks @leemaguire It is not reproducible 100% of the time directly but definitely is reproducible after 2-3 iterations for us. Issue is not limited to CarObject and happens with any type of Realm Object that has been modified.

We found a very similar issue in the community thread. Widgets indeed could have been the root cause, just like you pointed out

tgoyne commented 1 year ago

CarObject is only present in the app and not the widget, so if the widget performs the migration it has no way of updating the stored schema for CarObject. When the main app then opens the Realm, it sees the new schema version but old schema for CarObject.

tejuamirthi commented 1 year ago

So how should we handle this case @tgoyne? Can you please recommend a solution or a work around for this issue?

dianaafanador3 commented 1 year ago

@tejuamirthi are you adding the file/s containing the models to both targets (widget Extension and App), so whenever does the first open/migration they have the same schema?.

leemaguire commented 1 year ago

@tejuamirthi did you try the suggestion of having the models visible to all targets?

dianaafanador3 commented 1 year ago

Closing this as there is no response from the user.

tejuamirthi commented 1 year ago

Hey, sorry for the delay. For anyone referring this later, we have stopped initialising or using realm apis in extension. That solved the issue for us. We couldn't afford more data loss and hence couldn't test the above approach of making all models available to extensions.

dianaafanador3 commented 1 year ago

We do support using a local only Realm in App Extension, the only requirement will be that the configuration used to open the realm is the same, including the schema.

tejuamirthi commented 1 year ago

Thanks for clarifying

yasheedv commented 1 year ago

@dianaafanador3 how we can use a local only Realm in App Extension? Could you please provide a code sample?

We have a large database in our app, if we are not setting objectTypes in Realm.Configuration while accessing Realm from the widget extension, extension is crashing because of the memory limit.

If we are setting objectTypes in Widget Extension it's working fine without any crash but while launching the app, the migration is not happening for other realm objects and always getting the migration error in App level.

How we can solve this?