Angular throws this error when a signal is written to (with set or update) while a computed or a template is being evaluated. Both are expected to only read signals, so writing to one there would change state in the middle of computing it.
The error message says which of the two cases it is.
Writing to signals is not allowed in a computed
A computed should derive its value from other signals without side effects:
count = signal(1);
total = signal(0);
doubled = computed(() => {
this.total.set(this.count() * 2); // not allowed
return this.count() * 2;
});
If the value only depends on other signals, make it a computed itself instead of storing it:
Use linkedSignal if the value should also be writable, or an effect if the write is a side effect of the change.
The same error is thrown for writes inside the computation of a linkedSignal.
Writing to signals is not allowed while Angular renders the template
Template expressions run during rendering, so a method called from the template must not write to a signal either:
@Component({
selector: 'app-example',
template: '<p>{{ label() }}</p>',
})
export class Example {
views = signal(0);
label() {
this.views.update((v) => v + 1); // not allowed
return `Viewed ${this.views()} times`;
}
}
Move the write to where the change actually happens. Writing to signals is allowed in event listeners, lifecycle hooks, output handlers and effects.
Using untracked
A write wrapped in untracked does not throw. Use it only when the write is intentional and can't be moved, and keep in mind that signals read inside untracked are not tracked either.
Debugging the error
The stack trace points to the set or update call. From there, look for the computed, linkedSignal or template expression that called it.