realm-swift
realm-swift copied to clipboard
Fatal Exception: realm::KeyNotFound in Realm notification listener thread
How frequently does the bug occur?
Sometimes
Description
Since version 10.22.0, but it happens in 10.24.0 too, we started to see this crash for some users. It happens in random places.
For example:
Crashed: Realm notification listener
Fatal Exception: realm::KeyNotFound No object with key '99' in 'class_[OBJECT]'`
There's no stack trace for this crash.
The stracktrace below is what's happening on main queue, but like I said, it happens randomly... when we insert something or read something.
Stacktrace & log output
com.apple.main-thread
0 libsystem_kernel.dylib 0x2640 __psynch_mutexwait + 8
1 libsystem_pthread.dylib 0x23dc _pthread_mutex_firstfit_lock_wait + 84
2 libsystem_pthread.dylib 0x952c _pthread_mutex_firstfit_lock_slow + 248
3 libc++.1.dylib 0xf15c std::__1::mutex::lock() + 16
4 Realm 0x3957a4 realm::_impl::RealmCoordinator::register_notifier(std::__1::shared_ptr<realm::_impl::CollectionNotifier>) + 56
5 Realm 0x3d2488 realm::Results::prepare_async(realm::util::TaggedBool<realm::ForCallback>) + 640
6 Realm 0x3c94a0 realm::Results::ensure_up_to_date(realm::Results::EvaluateMode) + 416
7 Realm 0x3c8dc0 realm::util::Optional<realm::Obj> realm::Results::try_get<realm::Obj>(unsigned long) + 48
8 Realm 0x3c9174 realm::util::Optional<realm::Obj> realm::Results::first<realm::Obj>() + 68
9 Realm 0x12ffe0 RLMAccessorContext realm::Results::dispatch<auto realm::Results::first<RLMAccessorContext>(RLMAccessorContext&)::'lambda'(RLMAccessorContext&)>(RLMAccessorContext&) const + 412
10 Realm 0x12fe30 auto realm::Results::first<RLMAccessorContext>(RLMAccessorContext&) + 24
11 Realm 0x12dbe8 -[RLMResults firstObject] + 48
Can you reproduce the bug?
Not yet
Reproduction Steps
We wren't able to reproduce and few users are affected, but it happens repetitively for them.
Version
10.24.0
What SDK flavour are you using?
Local Database only
Are you using encryption?
No, not using encryption
Platform OS and version(s)
iOS 15.3.1
Build environment
Xcode version: Xcide 13.2.1 Dependency manager and version: Carthage
Hi @Bodnar-Dan Seems like the stack trace is not related to the crash, so we can't diagnose why this is happening. We may need more info to reproduce this. We do have a fix in our more recent release why fixes which may solve the issue Application would sometimes crash with exceptions like 'KeyNotFound' or assertion "has_refs()". Other issues indicating file corruption may also be fixed by this. The one mentioned here is the one that lead to solving the problem. Can you update to that version and check if this is still happening
Thank you, I will update and return with a feedback. I will also try to find more info about the crash.
I still see this in 10.25.0. One thing worth mentioning, this crash is happening when iOS is bringing back the app from background to connect to our paired BLE device. We have this Background Mode enabled and by the nature of this capability, iOS brings back the app from background to allow operations on BLE devices. We have this enabled for a few years and this was not changed in the recent releases. Also this happens on various iOS versions, not only the latest one...
@Bodnar-Dan Can I see a full stack trace for this crash, even though it seems like some realm related code is running in the main thread during the crash, the real crash is happening in the realm notification listener thread.
@Bodnar-Dan Can you provide the requested information so that we can investigate further?
@leemaguire sadly I don't have a stack trace of the crash. The crash is reported on the Firebase thread for a reason (I learned that this is a common issue). Maybe that's because often the crash is happening while the app is in background. Ofc, we're unable to reproduce it in any way.
We only have this (and similar), without additional information. What I can also tell, is that for a specific user, it's always the same key and the same object. So, 805 is not random.
Fatal Exception: realm::KeyNotFound
No object with key '805' in 'class_MyRealmObject'
And I guess the key
here is not the primary key, because in our case, the primary key is a String. 805 from the app point of view, means nothing.
We have 3 different Realms in our app (on different modules). All 3 Realm notification listener threads are looking normal.
Realm notification listener
0 libsystem_kernel.dylib 0x2e18 kevent + 8
1 Realm 0x3a8c68 realm::_impl::ExternalCommitHelper::listen() + 156
2 Realm 0x3a8db8 void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, realm::_impl::ExternalCommitHelper::ExternalCommitHelper(realm::_impl::RealmCoordinator&)::$_0> >(void*) + 52
3 libsystem_pthread.dylib 0x19ac _pthread_start + 148
4 libsystem_pthread.dylib 0xe68 thread_start + 8
All other threads are also not reporting any work.
This issue is not affecting a lot of users, but it's repetitive for them (once happening, it always happens). In our latest version, in the realm migration block we emptied the data stored for these affected objects, so all users were starting from scratch. I was under the impression this was triggered by some bad data. However, the crash is still visible (I really can't tell if it's for the same users). In the next version we'll rename the classes and basically let Realm recreate the structure, without migrating any data. Not sure if this is going to help... but it's worth trying.
found the same crash in Our project: Fatal Exception: RLMException No object with key '454' in 'class_RealmUser'
where... class RealmUser: Object { @Persisted(primaryKey: true) var uuid = "" .. }
it crashed on static Function static func getByPrimaryKey(uuid: String, realm: Realm? = try? Realm()) -> RealmUser? { guard let realm = realm else { return nil } return realm.object(ofType: RealmUser.self, forPrimaryKey: uuid) <--- here }
Found this crash too..
Fatal Exception: realm::KeyNotFound
We're running into this same exception/crash. We're using Realm 10.25.1. This happens rarely, but when it does happen, it is most often a case where we're in a write block trying to add/delete object A (object A contains a list property of object Bs), and the exception will be related to the primary key of object B.
Fatal Exception: RLMException
0 CoreFoundation 0x99288 __exceptionPreprocess
1 libobjc.A.dylib 0x16744 objc_exception_throw
2 Our Project 0x3bf80c RLMAccessorContext::createObject(objc_object*, realm::CreatePolicy, bool, realm::ObjKey) + 1097 (RLMAccessor.mm:1097)
3 Our Project 0x3c8740 void realm::Object::set_property_value_impl<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, realm::Property const&, objc_object* __strong, realm::CreatePolicy, bool) + 1125 (RLMAccessor.mm:1125)
4 Our Project 0x3bfce8 realm::Object realm::Object::create<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, std::__1::shared_ptr<realm::Realm> const&, realm::ObjectSchema const&, objc_object* __strong, realm::CreatePolicy, realm::ObjKey, realm::Obj*) + 355 (object_accessor.hpp:355)
5 Our Project 0x3bf4a8 RLMAccessorContext::createObject(objc_object*, realm::CreatePolicy, bool, realm::ObjKey) + 1093 (RLMAccessor.mm:1093)
6 Our Project 0x3c8740 void realm::Object::set_property_value_impl<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, realm::Property const&, objc_object* __strong, realm::CreatePolicy, bool) + 1125 (RLMAccessor.mm:1125)
7 Our Project 0x3bfce8 realm::Object realm::Object::create<objc_object* __strong, RLMAccessorContext>(RLMAccessorContext&, std::__1::shared_ptr<realm::Realm> const&, realm::ObjectSchema const&, objc_object* __strong, realm::CreatePolicy, realm::ObjKey, realm::Obj*) + 355 (object_accessor.hpp:355)
8 Our Project 0x3bf4a8 RLMAccessorContext::createObject(objc_object*, realm::CreatePolicy, bool, realm::ObjKey) + 1093 (RLMAccessor.mm:1093)
9 Our Project 0x408728 RLMAddObjectToRealm + 139 (RLMObjectStore.mm:139)
10 Our Project 0x55be9c Realm.add<A>(_:update:) + 432 (Realm.swift:432)
11 Our Project 0xd8b30 closure #2 in StoryRepository.cacheStories(stories:sectionIds:queueKey:deleteExisting:offset:realm:) + 521 (StoryRepository.swift:521)
12 Our Project 0x6f754 thunk for @callee_guaranteed () -> (@error @owned Error) (<compiler-generated>)
13 Our Project 0xdc4c8 partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) (<compiler-generated>)
14 Our Project 0x55b6b8 Realm.write<A>(withoutNotifying:_:) + 255 (Realm.swift:255)
15 Our Project 0xd89c0 StoryRepository.cacheStories(stories:sectionIds:queueKey:deleteExisting:offset:realm:) + 516 (StoryRepository.swift:516)
16 Our Project 0xd85e0 StoryRepository.insertStories(storyList:sectionIds:queueKey:deleteExisting:queue:offset:) + 492 (StoryRepository.swift:492)
17 Our Project 0xd7ec8 closure #1 in closure #3 in StoryRepository.remoteStories(sectionInfos:sectionSource:queue:page:limit:offset:query:cachedStories:isNotPaginated:) + 391 (StoryRepository.swift:391)
18 Our Project 0x6f754 thunk for @callee_guaranteed () -> (@error @owned Error) (<compiler-generated>)
19 Our Project 0xdc4c8 partial apply for thunk for @callee_guaranteed () -> (@error @owned Error) (<compiler-generated>)
20 Our Project 0xddc6c thunk for @callee_guaranteed () -> (@error @owned Error)partial apply
21 libswiftObjectiveC.dylib 0x1a10 autoreleasepool<A>(invoking:)
22 Our Project 0xdd11c partial apply for closure #3 in StoryRepository.remoteStories(sectionInfos:sectionSource:queue:page:limit:offset:query:cachedStories:isNotPaginated:) (<compiler-generated>)
23 Our Project 0x628ac8 closure #2 in ObservableType.do(onNext:afterNext:onError:afterError:onCompleted:afterCompleted:onSubscribe:onSubscribed:onDispose:) + 40 (Do.swift:40)
24 Our Project 0x628b3c partial apply for closure #2 in ObservableType.do(onNext:afterNext:onError:afterError:onCompleted:afterCompleted:onSubscribe:onSubscribed:onDispose:) (<compiler-generated>)
25 Our Project 0x629398 partial apply for closure #1 in ObservableType.do(onNext:afterNext:onError:afterError:onCompleted:afterCompleted:onSubscribe:onSubscribed:onDispose:)
26 Our Project 0x628dcc DoSink.on(_:) + 66 (Do.swift:66)
27 Our Project 0x628f90 protocol witness for ObserverType.on(_:) in conformance DoSink<A> (<compiler-generated>)
28 Our Project 0x643444 ObserveOnSink.run(_:_:) + 133 (ObserveOn.swift:133)
29 Our Project 0x6445ec partial apply for thunk for @escaping @callee_guaranteed (@unowned @callee_guaranteed () -> ()) -> () (<compiler-generated>)
30 Our Project 0x6517f8 partial apply for thunk for @escaping @callee_guaranteed (@in_guaranteed A, @unowned @callee_guaranteed @substituted <A> (@in_guaranteed A) -> () for <A>) -> () (<compiler-generated>)
31 Our Project 0x650f3c closure #1 in RecursiveImmediateScheduler.schedule(_:) (<compiler-generated>)
32 Our Project 0x626ea0 partial apply for closure #1 in DispatchQueueConfiguration.schedule<A>(_:action:) + 27 (DispatchQueueConfiguration.swift:27)
33 Our Project 0x27b4c thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>)
34 libdispatch.dylib 0x1e6c _dispatch_call_block_and_release
35 libdispatch.dylib 0x3a30 _dispatch_client_callout
36 libdispatch.dylib 0xb124 _dispatch_lane_serial_drain
37 libdispatch.dylib 0xbc80 _dispatch_lane_invoke
38 libdispatch.dylib 0x16500 _dispatch_workloop_worker_thread
39 libsystem_pthread.dylib 0x10bc _pthread_wqthread
40 libsystem_pthread.dylib 0xe5c start_wqthread
@starchey the stack trace doesn't mention the error on this issue, can you please attach a more detailed stack trace.
@starchey the stack trace doesn't mention the error on this issue, can you please attach a more detailed stack trace.
This is the full trace we're getting from Firebase. They all include Exception text like the following:
Fatal Exception: RLMException
No object with key '104' in 'class_OurObject'
No object with key '513' in 'class_RealmString'
We had a lot of crash reports from production users lately and we are unable to repro. We are on 10.32.3.
The code is just trying to access [RLMResult count]
property on a background thread
0 CoreFoundation 0x18f181e88 _exceptionPreprocess + 164
1 libobjc.A.dylib 0x1884bb8d8 objc_exception_throw + 59
2 Realm 0x1041dee9c RLMThrowResultsError(NSString*) (RLMResults.mm:112)
3 Realm 0x1041df100 -[RLMResults count] (RLMResults.mm:149)
4 APP 0x100f07ec8 buildCountMap #1 () in LMContactFilterButton.configureMenu() (LMContactFilterButton.swift:97)
5 APP 0x100f079c4 closure #1 in LMContactFilterButton.configureMenu() (LMContactFilterButton.swift:72)
6 APP 0x100cc0cbc thunk for @escaping @callee_guaranteed () -> () (<compiler-generated>:0)
7 libdispatch.dylib 0x1967504b4 _dispatch_call_block_and_release + 31
8 libdispatch.dylib 0x196751fdc _dispatch_client_callout + 19
9 libdispatch.dylib 0x196759694 _dispatch_lane_serial_drain + 671
10 libdispatch.dylib 0x19675a1e0 _dispatch_lane_invoke + 383
11 libdispatch.dylib 0x196764e10 _dispatch_workloop_worker_thread + 651
12 libsystem_pthread.dylib 0x1dc1d7df8 _pthread_wqthread + 287
13 libsystem_pthread.dylib 0x1dc1d7b98 $start_wqthread + 7
Sample code:
let results = \* realm query to get RLMResults *\
if results.count > 0 { \\ crash on `results.count`!!
...
}
This issue may be caused by a file corruption that without access to a realm file it is really hard to diagnose. There is a fix which will be available in a future release which may fix this corruption issue https://github.com/realm/realm-core/pull/5993 Be aware that the fix will not fix already corrupted files, but hopefully prevent creating corrupted files in the future..
This issue may be caused by a file corruption that without access to a realm file it is really hard to diagnose. There is a fix which will be available in a future release which may fix this corruption issue realm/realm-core#5993 Be aware that the fix will not fix already corrupted files, but hopefully prevent creating corrupted files in the future..
Thanks! Reading https://github.com/realm/realm-swift/issues/8000#issuecomment-1337012692, it sounds like this fix is included in v10.33.0, will update to that for our next release.
We still have the issue using Realm v10.33.0, but those could be users that have had their files corrupted when using the previous version.
@dianaafanador3 is there a way to catch file corruption exceptions so that we can handle them somehow, instead of crashing the app. Or is there any way for us to check the integrity of a Realm file?
Actually for this particular case, if you catch the error KeyNotFound
and ask the user or perform some actions after, which handle the issue somehow. (delete the realm file, for example)
In some other corruption cases, the assertion will make the app crash and there will be no way to handle the issue.
@bodnar-dan can you update to our latest version 10.35.0, there are some fixes related to this in core, which may fix this issue.
Hi, I'm using the latest release and i still get this error. I did some tests and i think it happens when we are observing changes for one specific key and then we delete the object and write new ones....
Hi @andrefmsilva are you able to reproduce this. Can you please share a sample code with the reproduction you are describing?
Hi @dianaafanador3, after some debug i found the problem for my case. My database was corrupted because i was deleting data using a predicate with properties that don't exist in the schema...
I don't know if it's the same problem for other users but the error after corruption was the same.
mmm interesting. Have you tried our Swift Type Safe Query API https://www.mongodb.com/docs/realm/sdk/swift/crud/filter-data/#std-label-ios-realm-swift-query-api, which may prevent this issues to happen in the future. This is probably something that should not be corrupting the data and an error should be throw in those cases. If you can provide a sample code, we can check it out and fix it if there is an issue.
I can't use the Query API with my current implementation because i have an abstraction layer that queries realm using some enum.
Basically each enum has cases to query a specific schema and knows how to create the Predicate (or NSCompoundPredicate) and NSSortDescriptor
@andrefmsilva The weird thing is that if you use our API for filtering using a predicate with a wrong property name, for example
let objectsToDelete = results!.filter("nam == 'Something'")
should be getting an error like the following
"Invalid keypath 'nam': Property 'nam' not found in object of type 'Todo'"
, unless you are using another type of filtering that is not using our API.
@bodnar-dan any updates from your side about this issue?
Same issue with Realm version 10.38.0 - iPadOS 12.2.0
HI @huutrung789 can you provide any more information about your issue, stack trace, sample code so we can reproduce this?.
We're closing this due to inactivity, but if you encounter a similar issue with the latest version of the Swift SDK, feel free to reopen.