RealmInvalidObjectException in release but not in debug mode

I wanted to learn about MAUI and MongoDB Realm by creating a basic .NET MAUI app using MVVM and Realm with Flexible Sync. It’s a very simple to-do list type of app. Full source code here in case it helps: https://github.com/kimgoetzke/listem.

Problem: In Debug mode, everything works as expected but in Release mode (emulator as well as device), I am getting Realms.Exceptions.RealmInvalidObjectExceptions when removing an item from the list using method 1.

  • Method 1: You can swipe-remove items (this is where the RealmInvalidObjectException occurs in Release mode)
  • Method 2: You can check a checkbox and all items that were selected will be removed when leaving the page (no problems here!)

Both methods use this flow:
ViewModel:

    [ObservableProperty] private IQueryable<Item> _items = null!;

    // Called in constructor
    public void GetSortedItems()
    {
        Items = RealmService
            .GetMainThreadRealm()
            .All<Item>()
            .Where(i => i.List == CurrentList)
            .OrderBy(i => i.Category!.Name)
            .ThenByDescending(i => i.UpdatedOn);
    }

    [RelayCommand]
    private async Task RemoveItem(Item item)
    {
        var previousStage = IsBusy;
        IsBusy = true;
        await _itemService.DeleteAsync(item);
        _listHasChanged = true;
        IsBusy = previousStage;
    }

Service:
`
public async Task DeleteAsync(Item item)
{
logger.Info(“Removing: {Item}”, item.ToLog());
var realm = RealmService.GetMainThreadRealm();
await realm.WriteAsync(() => realm.Remove(item));
}
``

The ContentView that invokes the RelayCommand has a CollectionView with ItemsSource="{Binding Items}" from the view model:
``
<SwipeView.LeftItems>

<SwipeItemView
Command=“{Binding Source={RelativeSource AncestorType={x:Type viewmodel:ListViewModel}}, Path=RemoveItemCommand}”
CommandParameter=“{Binding .}” // = Item
BackgroundColor=“{DynamicResource Green}”
WidthRequest=“400”>

// …


</SwipeView.LeftItems>
`

I’ve been spending waaay to much time trying all sorts of stuff but cannot figure it out and I assume it’s something that’s entirely obvious to someone who knows what they are doing.

What am I not understanding about Realm/Flexible Sync here that explains this? And how may I deal with it correctly?

Hi @Kim,

I did not have the time to run your code, but it looks definitely reasonable, there is nothing that jumps to the eye :smile:

We experienced various “unexpected” behaviours with MAUI, so I would say it would make sense to check if this is the case. So what I would suggest you to do is:

  • Check if RemoveItem is maybe called twice in Release mode. The exception you’re getting is obtained when you’re trying to do something with an object that is not in Realm anymore. So in this case I’m thinking it could happen if you’re trying to delete an object that has been already deleted.
  • I would check if the same happens on iOS (or other platforms you can possibly test on), or it’s a strictly Android-related issue.

Let us know

Thank you, @papafe - I appreciate our reponse. Not sure if it hadn’t been better if I’d just made silly noob mistake. :smiley:

I will do as you suggest, see what I can learn from it, and report back for future reference/follow up questions.

OK, so here’s an update:

Re :one: - I can confirm that RemoveItem is not called more than once in Release mode. From what I can see, the MAUI code appears to behave in the same way as compared to Debug mode.

Re :two: - Unfortunately, I failed to test other targets/platforms. I tried but it would have been too large of an endeavour to allow for a desktop build as I had built this app just for mobile (to keep it simple for learning purposes). Also, I don’t have macOS + iPhone so I cannot try iOS.

What else I have tried:

:three: - I have updated all sorts of dependencies (MAUI-related as well as Realm) that had updates in the meantime but this also didn’t help.

:four: - I have attempted to change the logic in all sorts of ways but none of the permutations made any difference except:

:five: - Instead of using IQueryable<Item> _items as an ObservableProperty, I have attempted replacing all usage of it by an ObservableCollection<Item> _observableItems which is a copy of the Realm-synced Items . The ObservableCollection is then used in the XAML but both Items and ObservableItems are updated when either has changed. This stops the RealmInvalidObjectException when swipe-removing (method 1 i.e. the initial problem) but the same error then occurs when selected items are removed upon leaving the page (method 2). Branch here (main no longer contains method 2 until everything works). In this branch, I have also plastered log statements before/after everything that’s invovled. At some seemingly random point when iterating through the list of items to delete, the Realm will throw the RealmInvalidObjectException, despite the code checking whether the item exists before even attempting to delete it (i.e. sometimes it’s the first item, sometimes the last, or any in between).

I would be happy to provide the logs but: Sorry, new users can not upload attachments and it’s just too much text to digest in a reply code box.

I would appreciate any other suggestions, ideas, or details on regarding the “unexpected behaviours with MAUI” that could give me pointers.

Hi @Kim ,

Thanks for your answer. I will try to investigate further and will get back to you

Hi @Kim ,

So far I had no luck trying to reproduce your error.

What I have tried:

  • Took the code from your main branch
  • In ListControl.Xaml I have set ItemsSource="{Binding Items}" in order to bind to the actual realm collection and not the ObservableCollection
  • I’ve modified RealmService.DeleteAsync in order to directly delete the object, without doing any query, as you’ve shown in your first post.
  • I am running on release on an Android Emulator. Using Jetbrains Rider on a Mac

So far I do not get any exception when deleting any element from the list with a swipe. Given this it is kinda difficult what could be the cause of your issue, but I have some considerations:

  • I am not sure if there is anything else in your project that could be causing this issue. I can see your project is quite complex, so there could be something I am missing. My suggestion would be to try to reproduce the error on a much smaller scale project, eventually even just using a local realm. This way it would also be easier to investigate for us.
  • I understand now you’re getting an exception, but you should definitely not need to copy all the elements of the list in the observable collection (so it was correct as you’ve shown in the first post).
  • In the same way you don’t need to call GetSortedItems again. Once you call it in the constructor you’re good to go

Overall I am sorry I do not have a clear help for your situation, but it is kinda difficult to investigate without having a repro case.

Hi @pepe_pepito, truly appreciate you looking into this! :pray: And I’m really sorry that I didn’t make the below much clearer in my last message:

Branch here (main no longer contains method 2 until everything works).

The main branch contains those weird ObservableCollection shinanigans (as it fixed the issue with method 1) and completely removes method 2 (which was then breaking due to the error). As a result, nothing should break on the main branch code, as you have seen.

The bug described in my previous post is only in this branch: fix-realminvalidobjectexception-on-swipe-delete. This means, on this branch the app will crash due to the RealmInvalidObjectException when you tick the checkboxes for a bunch of items and then leave the page (which will attempt to remove them from the realm).

Alternatively, you can see the original issue from my first post in action here: d1e024b. This is just prior to making the changes above i.e. in this version method 1 (swipe-removing items) will crash the app with a RealmInvalidObjectException at seemingly random points in time.

If it’s not too much to ask, would you be able to try one more time, ideally the original one (d1e024b i.e. the link in the previous paragraph) that I came here to ask for help for? :pray: It’s also significantly less complex as this is without any copies as ObservableCollection and no if-statements checking if the Realm item exists, etc. all over the place. Apologies for the confusion!

Just to add, I’m confident that you’ll be able to reproduce the issue quickly in any of those branches because I tested it across more than one (Windows) PC in different emulators and on several Android devices. Obviously, the issue will only occur in Release mode, not in Debug mode.

Hi @Kim

I manage to reproduce the error in release mode in the end. The trick is that it does not happen 100% of the time, and I thought it did instead.

I think that the root issue is caused by AutomationId. After removing all the places where it’s used in ListControl.xaml it’s not happening anymore it seems. I do not have experience with UI testing, but I suppose MAUI is trying to retrieve the AutomationId of the object that has been removed from the list in order to notify the testing framework. Given that the IDs were depending on properties of the realm objects, then you have the issue, as you cannot access properties of deleted realm objects. I am also not entirely sure of why this happens only in release mode.

1 Like

Thanks for trying again @papafe - this is an unexpected but very helpful insight! I will play around with it over the weekend, research this further and report back/mark your answer.

This topic was automatically closed 5 days after the last reply. New replies are no longer allowed.