How to debug "Expression Changed After It Has Been Checked" Error?
Asked Answered
P

3

7

This is a notorious error, which has a quite a "following" among developers, however it is also known to be quite tricky to debug. The log like this

PersonalSituationComponent.html:3 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'true'. Current value: 'false'.
at viewDebugError (core.es5.js:8434) [angular]
at expressionChangedAfterItHasBeenCheckedError (core.es5.js:8412) [angular]
at checkBindingNoChanges (core.es5.js:8576) [angular]
at checkNoChangesNodeInline (core.es5.js:12455) [angular]
at checkNoChangesNode (core.es5.js:12429) [angular]
at debugCheckNoChangesNode (core.es5.js:13209) [angular]
at debugCheckRenderNodeFn (core.es5.js:13149) [angular]
at Object.eval [as updateRenderer] (PersonalSituationComponent.html:3) [angular]
at Object.debugUpdateRenderer [as updateRenderer] (core.es5.js:13131) [angular]
at checkNoChangesView (core.es5.js:12251) [angular]
at callViewAction (core.es5.js:12618) [angular]
at execEmbeddedViewsAction (core.es5.js:12596) [angular]
at checkNoChangesView (core.es5.js:12250) [angular]
at callViewAction (core.es5.js:12618) [angular]

is not really helpful. And if one takes a lot at the line 3 of the html, the line has no booleans in it, but it is an opening tag for a component which does have some of them at various places (.ts and .html respectively).

How would you debug such an error, without replacing all booleans with hardcoded values and checking each one of them separately? (And while you are typing, I am going to do just that).

Pimental answered 25/10, 2017 at 12:48 Comment(1)
I know this is an old thread but I found the debugging of this to be the best blog.angular-university.io/angular-debugging.Diathermic
H
3

There are a lot of posts showing how to figure out the 'ExpressionChangedAfterItHasBeenCheckedError' error, however, a good starting point is reading this to understand what this error means: https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4

But, if you just want a lazy way of figuring this out, just start commenting things out to find the culprit that's causing this error. Once you isolate the causing line, then perhaps post again with the specific error of "when I have this line I then get this error" etc. We might be able to help you out better then.

If you still don't want to do that, then once you find the problematic code then just try some of the things the community usually recommends:

  • wrap your code with setTimeout (this is just a hack)
  • run change detection detection as explained on another answer by @Milo
  • make sure the child element is being properly destroyed

There are a lot of posts on this error and if you put a little more effort and give us a better picture of your code then we might be able to help you out better.

Good luck! :)

Hatteras answered 25/10, 2017 at 13:8 Comment(1)
Upvoted for (yet unseen) detailed article. :) I am now at line 8406 of core.es5.js right before the error is thrown and trying to go backwards from there. The most weird thing until now, that most of the booleans the component uses are getters, which should trigger ChangeDetection on their own, right?... :/Pimental
E
1

You have to literally debug, because currently angular does not provide any meaningful details except value.

If you set debugger option break on all errors you will be able to walk through stack (kinda obvious right?) and see component name where problem occurs.

Edington answered 25/10, 2017 at 14:26 Comment(2)
Well, this is exactly what I am doing now. I have found the method where it all happens (in the controller), however changeDetectorRef.detectChanges() doesn't help. But that's another story.Pimental
You should be able to find component name and then it might be easier to guess which binding causes error. See github.com/angular/angular/issues/10131.Edington
C
0

You can run manual change detection on variable value changes that you suspect within the component until the error is resolved. Once you find it you can decide whether to re-design the implementation or just have the manual change detection run.

import { ChangeDetectorRef } from '@angular/core';

constructor(private _cdRef: ChangeDetectorRef) { }

this._cdRef.detectChanges();
Chinkapin answered 25/10, 2017 at 12:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.