Error while updating object property in flutter. Error code: 2005

Hello, I have a flutter project where I want to update an object property but I get this error:
Error: RealmException: Trying to modify database while in read transaction. Error code: 2005.

I tried all the documentation but still cannot solve the problem. Anyone can help me to solve it?

Here is my project: https://drive.google.com/file/d/1iDfK1m2AR2v1YfDeA3N-zptoKlJe9q4R/view?usp=sharing

Can you post the code that actually triggers the exception?

The exception says I’m trying to modify database while in read transaction, but db.isInTransaction here always output false.

  Future<void> updateFood(void Function() updateCallback) async {
    final db = await dbConn.realm;
    debugPrint(db.isInTransaction.toString());
    await db.writeAsync(updateCallback);
  }

The updateFood method calls writeAsync.

Future<void> updateFood(void Function() updateCallback) async {
    final db = await dbConn.realm;
    await db.writeAsync(updateCallback);
  }

Here is my code. Exception raised when this line is called:

foodsManager.allFoods[i].listOrder = i;

I want to update listOrder inside the onReorder event.

Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Reorder"),
      ),
      body: SafeArea(
        child: Obx(
          () => ReorderableListView(
            onReorder: (oldIndex, newIndex) async {
              setState(() {
                final newIdx = newIndex > oldIndex ? newIndex - 1 : newIndex;
                final item = foodsManager.allFoods.removeAt(oldIndex);
                foodsManager.allFoods.insert(newIdx, item);
              });

              for (var i = 0; i < foodsManager.allFoods.length; i++) {
                await foodsManager.updateFood(() {
                  foodsManager.allFoods[i].listOrder = i;
                });
              }
            },
            children: foodsManager.allFoods
                .map(
                  (e) => ListTile(
                    key: Key(e.hashCode.toString()),
                    leading: ClipRRect(
                      borderRadius: BorderRadius.circular(10),
                      child: Container(
                        color: null,
                        height: 20,
                        width: 20,
                      ),
                    ),
                    title: Text(e.text!),
                    trailing: const Icon(Icons.reorder),
                    onTap: () {},
                  ),
                )
                .toList(),
          ),
        ),
      ),
    );
  }

And another weird thing is that when I read only one type of objects , the exception will not raise.


  RxList<FoodTag> allFoodTags = <FoodTag>[].obs;

  late final Future<List<FoodTag>> getTags = _getTags();
  Future<List<FoodTag>> _getTags() async {
    final db = await dbConn.realm;
    allFoodTags.clear();
    allFoodTags.addAll(db.all<FoodTag>());
    return allFoodTags;
  }


  RxList<FoodItem> allFoods = <FoodItem>[].obs;

  late final Future<List<FoodItem>> getFoods = _getFoods();
  Future<List<FoodItem>> _getFoods() async {
    final db = await dbConn.realm;
    allFoods.clear();
    allFoods.addAll(db.all<FoodItem>());
    allFoods.sort(
      (a, b) => a.listOrder.compareTo(b.listOrder),
    );
    return allFoods;
  }

 Widget build(BuildContext context) {
    final foodsManager = Get.put(FoodsManager());
    foodsManager.getFoods;
    final tagsManager = Get.put(TagsManager());
    tagsManager.getTags; //If i comment this line, the exception will gone.

    return MaterialApp(
      ...
      ...
    );
  }

Still cannot solve the problem.
Once I read two types of objects into list, the exception raises.
But if I read only one type of object from db, there will be no exception with the same update code.

Once I used realm with multiple schemas, this exception raises. Even set a single property. I’m already wrap my code in write or writeAsync method but the error keep saying I’m trying to modify property in read transaction. Need help.

The problem is that your code has a race condition, which leads to multiple realm instances getting opened. The race condition is in this code:

  Future<Realm> get realm async {
    if (_realm != null) {
      return _realm!;
    } else {
      _realm = await _initDB(notesDBFileName);
      return _realm!;
    }
  }

  Future<Realm> _initDB(String filePath) async {
    final dbPath = join(Configuration.defaultStoragePath, notesDBFileName);
    final config = Configuration.local(
      [FoodItem.schema, FoodTag.schema],
      path: dbPath,
      initialDataCallback: initData,
      shouldDeleteIfMigrationNeeded: kDebugMode,
    );
    return Realm(config);
  }

Because you only assigning _realm after the future resolves, there’s a brief window where db.realm is called twice and _realm is still null. That causes two different realm instances to get opened - then only one will start a write transaction, while the other will not. There’s no reason for _initDB to be a future, so if you convert it to a regular synchronous function, things work as expected.

Thanks very much, the problem is solved! And I will check all similar
async method calls.