Understanding the "Expression has changed after it was checked" error

I am receiving an error when trying to update the value of an item in my app.

This is the error:

ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'.

In my project, I have a list of items:

<ion-item-sliding *ngFor="let item of items" [id]="'item-' + item.id">
    <ion-item lines="full">
          <ion-label [class.strike]="item.checked" class="ion-padding ion-text-wrap">
                {{ item.title }}
           </ion-label>
           <ion-checkbox slot="start" [checked]="item.checked" mode="ios" (ionChange)="itemChecked(item)"></ion-checkbox>
    </ion-item>
    <ion-item-options side="end">
          <ion-item-option (click)="move(item)">Move</ion-item-option>
     </ion-item-options>
</ion-item-sliding>

In my move method, I attempt to set the values like this, before saving in my database:

async move(item: Item) {
    item.location = 'history'; //No issues with this
    item.checked = false; //Throws above error
    await this.firestore.updateItem(item);
}

No errors are thrown if I just update the location, but as soon as I attempt to update the checked in the item, then it throws the error above?

Any thoughts on what may be causing this error and what I could look at to try and correct the issue?

What does itemChecked() look like?

This is my itemChecked method. Instead of updating the entire item in firestore, it just updates one item in the object based on the key.

async itemChecked(item: Item) {
    item.checked = !item.checked;
    await this.firestore.updateItemKey(item, 'checked');
}

The fundamental problem is that checked is getting modified multiple times within the same change detection cycle. One way you could try to debug it is to make checked have a custom setter function and put a breakpoint in it. It should get called at least twice quickly in succession in response to a click on the “move” before the NG0100 bites you. I’m speculating that this will be once from move and once from itemChecked.

Thanks for the detailed response. Just so I make sure I am on the same page, are you thinking that since both move and itemChecked are on the same element item (ion-item-sliding), that’s what’s causing the Expression error?

I’m not sure I am following your thoughts on the custom setter function, can you elaborate a little more so I could try that route too?

Much appreciated!

Edit: Additionally, I do notice this after I interact with the list:

After the initial load of the items (the first list.page.ts), I click on the an itemChecked() and it shows the result of the item (true) then it quickly loads the list two additional times.

Something along those lines.

This.