Realm-js: "realm.objects()" will return an number

Created on 18 Jan 2018  路  20Comments  路  Source: realm/realm-js

Goals

Get all results

Expected Results

realm.objects('Video') should return an array

Actual Results

A number is returned, almost half, looks like not the count of the result.

Steps to Reproduce

Code Sample

````
var realm;

this.allVideos = () => {
console.log(this.allVideos: ${this}, ${this.realm});

const videos = this.realm.objects('Video');
if (videos.length === undefined) {
console.log(!!!! Find a Realm\'s bug: videos should be array but it is ${videos});
return null;
} else {
console.log(allVideos: ${videos.length} ${videos});
}

return videos;
}
````

My log

!!!! Find a Realm's bug: videos should be array but it is 1

Version of Realm and Tooling

  • Realm JS SDK Version: 2.2
  • Node or React Native: 0.29
  • Client OS & Version: iOS 11
  • Which debugger for React Native: Chrome
O-Community Reproduction-Required T-Bug

Most helpful comment

Hello, just want to share with you how I fixed this issue:

I have replaced all my addListener(this.listener); with the following
addListener((results)=>setImmediate(this.listener, results));

Realm guys, I guess this should give you hint where to find the bug
Hopefully it will save a day someone )))

All 20 comments

videos.length should not be undefined. Please verify that videos is a Realm.Results object.

Find a Realm's bug: videos should be array but it is 1

I have actually stumbled upon a bug, that sounds similar to this.

In my case, I was debugging the app. I had a code where I try to get a collection with Realm.objects(whatever). And If I try to get a collection from inside Realm.write's callback, I get 1 instead of a collection. Only in debug mode.

I'll write more details later.

@angly-cat yes, It only happened if I enable remote debug. But Im very sure it is NOT in a Realm.write callback

But Im very sure it is NOT in a Realm.write callback

Yeah, I was able to catch a number instead of a collection outside of Realm.write. This number in my case was the amount of elements in that particular collection. It's not just a random number.

At first this bug was just freezing my app to death instead of showing any errors.

But in the end I was able to fix it in my codebase. It happens if several conditions are met. Can't say for sure, but in my case:

  1. I add a listener on this collection at first.
  2. I take a snapshot of this collection and then tried to remove some obsolete objects from within collectionSnapshot.forEach callback.

After I moved Realm.delete outside, the bug has gone.

Maybe in the near future I'll create a repo with minimal testcase for this bug.

It is an important observation that you only see when debugging. It could indicate that the communication between the browser and the device is not always doing what it is supposed to do. Since Realm objects are managed by Realm on the device, we have to copy data between the debugger and the device (no Realm in the browser).

@angly-cat Thank you for going so deep in order to find the triggering conditions. It would be super if you can provide us with a minimal testcase.

Thank you for going so deep in order to find the triggering conditions.

You're welcome.

It would be super if you can provide us with a minimal testcase.

I think I'll do that. No promises, though. And I can't say how soon I would've been able to do that.

Here you go. The testcase repo for Android. I can reproduce the bug on almost every run of the test app in debug mode with Chrome DevTools. I don't know if the testcase is minimal, but it should suffice. Let me know if it won't work for you and I'll think of something else.

@angly-cat Thanks!

This happens to me as well. I'm using React Native, Realm 2.4.0, and running an app on the iOS simulator.

@loganallenc But only when debugging?

Yes.

@loganallenc Great, that reduces the search space.

Anything new on this topic @kneth ? Are you on it? It makes development really hard for us atm.

Hey @ygweric or @loganallenc or @kneth , did you already found a solution or workaround? I'm not deep enough into the native code to find an own fix, yet. Would be happy about any tipps.

I have a write option where we do .map() to change several objects. After this, we see the issue. Could it be related?

try {
    realm.write(() => {
      let measurementItem = realm.create(MeasurementItem.schema.name, {
        id: uuid.v1(),
        date: new Date(),
        createdTimestamp: new Date()
      }, true);

      values.map(function (valueObject){
        valueItem = realm.create(ValueItem.schema.name, {
          id: uuid.v1(),
          value: valueObject.value,
          isSpecial: valueObject.isSpecial,

          category: valueObject.category,

          createdTimestamp: new Date()
        }, true);

        console.log("DB: valueItem: ", valueItem);
        if(valueItem==null){console.error("DB: ValueItem is null", valueItem)}

        //measurement.values.push(valueItem);
        valueObject.category.values.push(valueItem);
      });

    });
  } catch (error) {
    console.error(error);
  }

@leokaessner I don't think it is related to .map(). I haven't had time to dive into it but my best guess is that the debugger and device get out-of-sync when it comes to the result of the objects() call.

Apparently, when debugging with Chrome DevTools and in a collection's listener callback, accessing the collection by reference stored outside leads to problems. RPC calls start returning inconsistent results, like call A receives something, then subsequent call B receives results that should've been returned for A, then C receives B's results etc. (like in my case .length of a collection with complex objects returned false (a value of another field requested previously) and subsequent [0] of the collection returned a number (the length of the collection)). When I started accessing the collection by first argument of the callback, the issue resolved for me. I expected those two references to be somewhat equal, and they indeed both work equally when not debugging with Chrome.

const originalCollectionRef = realm.objects(model).filtered(filter);

originalCollectionRef.addListener((updatedCollectionRef, changeset) => {
    // const length = originalCollectionRef.length; // Wrong way.
    const length = updatedCollectionRef.length; // Right way.
    ...
});

I have the same issue, but objects return string. How to fix it?

Hello, just want to share with you how I fixed this issue:

I have replaced all my addListener(this.listener); with the following
addListener((results)=>setImmediate(this.listener, results));

Realm guys, I guess this should give you hint where to find the bug
Hopefully it will save a day someone )))

Ran into this as well. Can confirm it was occurring while debugging.

Solved by converting the RealmObject into a plain object _immediately_.

const objs = realm.objects(MessageSchema.name).map(function(obj){
  return {
    id: obj.id,
    name: obj.name
    ...
  }
});
console.log("objects", objs);

if you're relying on realm for dynamic models/collections obviously this won't help

Hello, just want to share with you how I fixed this issue:

I have replaced all my addListener(this.listener); with the following
addListener((results)=>setImmediate(this.listener, results));

Realm guys, I guess this should give you hint where to find the bug
Hopefully it will save a day someone )))

This causes other problems. Using this change in our app causes a problem with UI updates in certain conditions. We have a realm object with a field that gets updated via a time picker being opened on the device. The object in realm gets updated, but the change does not get reflected in the UI until the user touches the screen again after the time picker is closed. Removing setImmediate gets rid of this delay

Was this page helpful?
0 / 5 - 0 ratings

Related issues

max-zu picture max-zu  路  3Comments

camslaz picture camslaz  路  4Comments

MihaelIsaev picture MihaelIsaev  路  3Comments

kontinuity picture kontinuity  路  3Comments

blagoev picture blagoev  路  3Comments