Angular: Understand the ‘Expression Changed After It Has Been Checked’ Error

This might be the most confusing Angular error. It doesn’t quite tell you where the issue, nor how to fix it. And it only appears in development environments. If you google it, proposed solutions are usually to use a setTimeout somewhere, and that would actually work. And even though it looks like an ugly workaround, it might actually be a good solution.
But where is this issue coming from exactly? How do we fix it / why is a setTimeout a solution? As it is only in development environments, can’t we just ignore it?
Understanding this error requires some understanding of Angular change detection. That can be a pretty tricky interview question. The basic idea behind this error is that a child component is changing a property of a parent component. This is not exactly forbidden, but Angular has a top-to-down logic: parents should be setting values in children, not this other way around. If a child changes a value in a parent component, too early, that is to say within one change detection cycle, Angular will throw this error.
Let’s give an example with a child component:
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
@Input() name!: string;
}{{name}}and a parent component:
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss']
})
export class ParentComponent {
name = 'Parent name';
}<app-child [name]="name"></app-child>This is completely fine and doesn’t cause any error. If the child component changes this name property on init though, the ExpressionChangedAfterItHasBeenCheckedError appears:
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
@Input() name!: string;
@Output() nameChanged = new EventEmitter<string>();
ngOnInit(): void {
this.nameChanged.emit('Child name');
}
}<app-child [name]="name" (nameChanged)="name = $event"></app-child>
Where does that come from exactly?
Without going into too much details, we need to talk a bit about the Angular change detection. The ultimate aim for Angular is to generate the DOM depending on your components and their properties. When you pass a property down from a parent to a child component, Angular goes through different steps. In our case, for a first rendering, Angular will:
- set the value of name in the child component (the name variable, not yet what is displayed in the DOM)
- call ngOnInit, ngDoCheck on the child component
- update the DOM
- call ngAfterViewInit on the child component
In the development environment, and in the development environment only, Angular will then add a verification step after the fourth step. It keeps the values it used in the step 1 to step 4 and compares them to the values it has at the end. And if it isn’t the same, it throws an error.
To come back to our example, in the step 1 Angular keeps the value “Parent name” as oldValue. Then in the step 2, the ngOnInit of the child component is called, so the name value in the parent becomes “Child name”. At the end of the cycle, Angular compares oldValue and the new name value, they aren’t the same, an error is thrown.
So, to say it simply, the issue is happening because we change the value of name too early. A solution, if we really have to change the value in the child component, is therefore to change it later. That’s why wrapping the code in setTimeout works: you are changing the value of the name way after Angular is done, in a new VM turn.
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss']
})
export class ChildComponent implements OnInit {
@Input() name!: string;
@Output() nameChanged = new EventEmitter<string>();
ngOnInit(): void {
setTimeout(() => {
this.nameChanged.emit('Child name');
});
}
}You are probably not directly changing a parent property in your child component’s initialisation though. So why do you get this error?
While your case might not be as straight forward, the idea has to be the same, you must be changing the value of some attribute from the child up into the parent. It is most likely happening in a service (and your child and parent component are sharing a same value from it) or in a directive.
As this error only appears in development, you might also be tempted to just ignore it. It does only happen in development because Angular doesn’t perform this extra check in other environments. It doesn’t mean that can’t cause issues. Values are meant to be passed down in Angular. This error is telling you that you are changing a value “up”. This can’t be good.
In Plain English
Thank you for being a part of our community! Before you go:
- Be sure to clap and follow the writer! 👏
- You can find even more content at PlainEnglish.io 🚀
- Sign up for our free weekly newsletter. 🗞️
- Follow us on Twitter(X), LinkedIn, YouTube, and Discord.




