Skip to content

[Ivy] ASSERTION ERROR: Should be run in update mode #32756

Open

Description

@fr0

🐞 bug report

Affected Package

The issue is caused by package @angular/core (Ivy)

Is this a regression?

Yes, works in non-Ivy.

Description

I suspect this happens as a result of having an Input property that is set directly (isExpanded="true") instead of using a binding ([isExpanded]="true"), and having the property setter call changeDetectorRef.detectChanges(). It should be noted that this works in non-ivy.

🔬 Minimal Reproduction

https://github.com/fr0/angular-test/tree/ivy

  1. Clone repo
  2. git checkout ivy
  3. npm install
  4. npm start
  5. Open http://localhost:4200 in Chrome
  6. View browser console log

🔥 Exception or Error


core.js:5829 ERROR Error: ASSERTION ERROR: Should be run in update mode
    at throwError (core.js:1164)
    at assertEqual (core.js:1123)
    at refreshView (core.js:12425)
    at detectChangesInternal (core.js:13907)
    at ViewRef.detectChanges (core.js:15373)
    at ExpandableIfComponent.set isExpanded [as isExpanded] (expandable-if.component.ts:60)
    at setInputsFromAttrs (core.js:13579)
    at postProcessDirective (core.js:13335)
    at instantiateAllDirectives (core.js:13234)
    at createDirectivesInstances (core.js:12618)

🌍 Your Environment

Angular Version:




Angular CLI: 9.0.0-next.5
Node: 12.6.0
OS: darwin x64
Angular: 9.0.0-next.7
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-next.5
@angular-devkit/build-angular     0.900.0-next.5
@angular-devkit/build-optimizer   0.900.0-next.5
@angular-devkit/build-webpack     0.900.0-next.5
@angular-devkit/core              9.0.0-next.5
@angular-devkit/schematics        9.0.0-next.5
@angular/cli                      9.0.0-next.5
@ngtools/webpack                  9.0.0-next.5
@schematics/angular               9.0.0-next.5
@schematics/update                0.900.0-next.5
ng-packagr                        5.5.1
rxjs                              6.5.3
typescript                        3.5.3
webpack                           4.40.2
    

Activity

  1. added this to the needsTriage milestone on Sep 18, 2019
  2. mhevery commented on Oct 8, 2019

    @mhevery
    Contributor

    Please provide minimal reproduction with exact steps on how to reproduce it. We have limited time and can't go explore your application.

  3. fr0 commented on Oct 8, 2019

    @fr0
    Author

    The error occurs for me under angular 9.0.0-next.5 (which is what the linked ivy branch in the linked repo uses) when I run ng serve and launch http://localhost:4200.

    So:

    1. Clone repo
    2. git checkout ivy
    3. npm install
    4. npm start
    5. Open http://localhost:4200 in Chrome
    6. View browser console log
  4. fr0 commented on Oct 9, 2019

    @fr0
    Author

    I verified that the problem still occurs with 9.0.0-next.8.

  5. kara commented on Oct 15, 2019

    @kara
    Contributor

    @fr0 Thanks, I was able to reproduce. We'll add this to the list!

  6. SebastianPodgajny commented on Oct 24, 2019

    @SebastianPodgajny

    @kara We are using angular without ngZone and this issue is happening all over our code base because we have a lot of manual change detection with cdRef.detectChanges()
    Here is another example of this kind of error
    image
    image
    image
    image

    Angular CLI: 9.0.0-next.15
    Node: 12.10.0
    OS: darwin x64
    Angular: 9.0.0-next.13
    ... animations, common, compiler, compiler-cli, core, forms
    ... language-service, platform-browser, platform-browser-dynamic
    ... platform-server, router
    
    Package                            Version
    ------------------------------------------------------------
    @angular-devkit/architect          0.900.0-next.15
    @angular-devkit/build-angular      0.900.0-next.15
    @angular-devkit/build-ng-packagr   0.900.0-next.15
    @angular-devkit/build-optimizer    0.900.0-next.15
    @angular-devkit/build-webpack      0.900.0-next.15
    @angular-devkit/core               9.0.0-next.15
    @angular-devkit/schematics         9.0.0-next.15
    @angular/cdk                       9.0.0-next.0
    @angular/cli                       9.0.0-next.15
    @ngtools/webpack                   9.0.0-next.15
    @schematics/angular                8.0.1
    @schematics/update                 0.900.0-next.15
    ng-packagr                         9.0.0-rc.0
    rxjs                               6.5.3
    typescript                         3.6.4
    webpack                            4.41.2
    
  7. pkozlowski-opensource commented on Oct 29, 2019

    @pkozlowski-opensource
    Member

    @SebastianPodgajny the case you are mentioning seem to be different as compared to the originally reported here (different error message, different case).

    Could you please open a new issue and provide a reduced reproduction scenario? Thnx!

  8. 18 remaining items

  9. added
    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgent
    and removed on Oct 1, 2020
  10. sviat9440 commented on Oct 12, 2020

    @sviat9440

    Temporary fix for me:
    replace call detectChanges() to markForCheck().

  11. qpi commented on Dec 16, 2020

    @qpi

    I have the same issue under Angular 10 when call detectChanges(). I tried to upgrade to 11 but still the same

  12. id1945 commented on Jan 11, 2021

    @id1945

    I found that placing detectChanges() in the constructor caused an error. So I wrote it in the ngOnInt() function and it works properly with my project.
    I hope to help someone here

  13. jelbourn commented on Jan 28, 2021

    @jelbourn
    Contributor

    Copying notes on this from an internal tracker:

    In the example, the input setter calls detectChanges, which throws because it’s an unbound input and thus set in creation mode (and refreshView is only callable in update mode.)

    The question is - should we allow change detection to run in creation mode at all? In View Engine, we would throw if change detection was called in a directive constructor. But we allowed CD calls in input setters because inputs were always set in update mode.

    We could call renderView in detectChangesInternal to fix the refreshView error, but then we would still end up calling change detection in the middle of creation mode, which violates a lot of our assumptions. We would end up calling lifecycle hooks for child components too, which would mess up child component lifecycle hook order.

    We need to have a longer conversation about:

    whether we should allow sync change detection in setters

    whether we should abandon setting unbound inputs in creation mode bc it causes weirdness

  14. added a commit that references this issue on Feb 13, 2021
  15. sciborrudnicki commented on Feb 15, 2021

    @sciborrudnicki

    I use setTimeout(() => this.changeDetector.detectChanges(), 0);

  16. aksheyjhalani27 commented on Feb 16, 2021

    @aksheyjhalani27

    Any updates so far on this.?

  17. s3nt1n3lz21 commented on Mar 17, 2021

    @s3nt1n3lz21

    This error appeared when I was calling detectChanges() in the constructor after subscribing to some data. I moved the subscription and detectChanges() to ngOnInit() instead and it disappeared.

  18. blyndcide commented on Jun 11, 2021

    @blyndcide

    In Angular 12 this is happening even when not in a constructor. Simply calling .detectChanges() in an observable that, I don't know...initially runs too early and fast?, throws this error. Constructor has nothing in the body.

  19. joepvl commented on Jun 23, 2022

    @joepvl

    If you're running into this when writing tests and mocking a normally async call using of(yourMockedResult), it could be because your component's code is subscribing to the observable in the constructor and calling changeDetectorRef.detectChanges() in the callback. Because the call is async in your application, this does not pose an issue when running it, but mocking the observable using of(...) is making it sync in this case, which is why Angular complains. A pragmatic solution: use of(yourMockedResult).pipe(delay(0)) instead, which forces the observable to be async. That way, the changeDetectorRef.detectChanges() call will be pushed further along in the event loop, giving Angular a chance to put everything in place. (That said, it's probably a good idea to move it to ngOnInit if you can.)

  20. brianpooe commented on Aug 23, 2023

    @brianpooe

    Some of us cannot move the logic from the constructor to ngOnInit cause the application does not update as expected in that case using onPush strategy.

  21. arturovt commented on Sep 29, 2026

    @arturovt
    Contributor

    @JeanMeche this can be closed. Same class as #45577: a static attribute input is applied during creation, so calling detectChanges() from the setter re-enters change detection while the view is still in creation mode, which the assertion is reporting correctly rather than hiding.

    Reported against 9.0.0-next.7 in 2019, milestone v9.x-candidates, no upvotes, no comments, and the framing is an Ivy-versus-ViewEngine regression, so the comparison cannot be run any more.

    Running view work from an input setter is not supported: ngOnInit or afterNextRender is the place for it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3An issue that is relevant to core functions, but does not impede progress. Important, but not urgentarea: coreIssues related to the framework runtimecore: change detectionfreq2: medium

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions