Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[3.1.0] Cannot create new tag for model after its been destroyed error during test teardown #16541

Closed
Dhaulagiri opened this issue Apr 18, 2018 · 12 comments

Comments

@Dhaulagiri
Copy link
Contributor

Beginning in Ember 3.1 we have a test that is failing on teardown with this error:

Assertion Failed: Cannot create a new tag for <model-b::ember2555:1> after it has been destroyed.

Working up a reproduction is going to be hard so I'll do my best to describe the scenario:

There is a model A that has a belongsTo relationship with a model B.

Model A also has readOnly properties that depend on properties in model B a la isTrue: readOnly('modelB.someProp'). Where someProp on model B is an equal computed.

The above assertion seems to be getting triggered during teardown as ember-metal tries to unwatch each of the computed properties that depend on some property on the related model. As far as I can tell this does not occur while running the app.

I can make the error go away by either removing these computed properties (not really a solution) or setting the relationship to async: false.

I'm not sure if this is a regression per se, but I'm also not really sure how to best dig in and figure out how or where to fix this.

@rwjblue
Copy link
Member

rwjblue commented Apr 18, 2018

I think it would be useful to see more of the stack (there are a couple of different pathways that end up calling meta.writableTag and we need to know which to dig into...).

The thing that seems somewhat odd in this case (and what we need to figure out) is why unwatching would cause meta.writeableTag to be called at all. Personally, I would only expect it to be called when a given object is getting rendered in a template...

@Dhaulagiri
Copy link
Contributor Author

@rwjblue here is the full stack

Error: Assertion Failed: Cannot create a new tag for `<model-b::ember2555:1>` after it has been destroyed.
    at new EmberError (http://localhost:7357/assets/vendor.js:35404:25)
    at Object.assert (http://localhost:7357/assets/vendor.js:35654:15)
    at Meta.writableTag (http://localhost:7357/assets/vendor.js:47269:54)
    at tagFor (http://localhost:7357/assets/vendor.js:45456:22)
    at contentFor (http://localhost:7357/assets/vendor.js:58496:60)
    at Proxy.unknownProperty (http://localhost:7357/assets/vendor.js:58540:21)
    at Object.get (http://localhost:7357/assets/vendor.js:60891:50)
    at removeListener (http://localhost:7357/assets/vendor.js:44554:42)
    at removeObserver (http://localhost:7357/assets/vendor.js:45824:5)
    at Proxy.didUnwatchProperty (http://localhost:7357/assets/vendor.js:58537:38)

@rwjblue
Copy link
Member

rwjblue commented Apr 18, 2018

Gotcha, so its our old friend "the proxy assertion" 😅.

My first suggestion (which may need more digging) would be to add a guard here to avoid calculating contentFor when the proxy itself is destroying.

That might look like:

  unknownProperty(key) {
    if (this.isDestroying || this.isDestroyed) { return; }

    let content = contentFor(this);
    if (content) {
      return get(content, key);
    }
  },

However, I am also curious what property is here after that removeListener call...

@Dhaulagiri
Copy link
Contributor Author

Dhaulagiri commented Apr 18, 2018

I think property is didRemoveListener at that point.

@rwjblue
Copy link
Member

rwjblue commented Apr 18, 2018

Hmm, I think that should have been addressed by #16404 which I missed when doing 3.1.0 but @rondale-sc backported to release (scheduled for 3.1.1) for us in #16496. Can you test the latest release build and see if this is already fixed there?

@Dhaulagiri
Copy link
Contributor Author

I have a feeling I may have trolled us with this issue so for that I apologize. I could have sworn I did try the latest release build this morning and still saw the error. However, in trying to reproduce this against ember master locally I couldn't reproduce it and now that I switch back to the latest release once again I also can't reproduce it. I don't even know which way is up anymore! 😵

Switching back to 3.1.0 release version does exhibit the error so that I think we can consider this resolved and I'll await a new release.

@Kilowhisky
Copy link

Kilowhisky commented May 3, 2018

I'm going to bring this back and say i'm experiencing this but it relies upon ember data also being at the latest version.

Interesting thing though is that it takes 3 tries to get it to do it. Check out the video in the attached zip

Cannot create a new tag for error.zip

My edit route unloads the models loaded in the willTransition hook.

Versions:

DEBUG: -------------------------------
ember-console.js:43 DEBUG: Ember             : 3.1.1
ember-console.js:43 DEBUG: Ember Data        : 3.1.1
ember-console.js:43 DEBUG: jQuery            : 3.3.1
ember-console.js:43 DEBUG: Ember Simple Auth : 1.6.0
ember-console.js:43 DEBUG: **-------------------------------**

Error:

"Error: Assertion Failed: Cannot create a new tag for `<sky-router-3@model:asset-profile-set-revision::ember4953:413>` after it has been destroyed.
    at new EmberError (http://localhost:4200/skyrouter3/assets/vendor.js:36764:25)
    at Object.assert (http://localhost:4200/skyrouter3/assets/vendor.js:37014:15)
    at Meta.writableTag (http://localhost:4200/skyrouter3/assets/vendor.js:48659:54)
    at tagFor (http://localhost:4200/skyrouter3/assets/vendor.js:46846:22)
    at contentFor (http://localhost:4200/skyrouter3/assets/vendor.js:59886:60)
    at Proxy.unknownProperty (http://localhost:4200/skyrouter3/assets/vendor.js:59930:21)
    at get (http://localhost:4200/skyrouter3/assets/vendor.js:49196:18)
    at _getPath (http://localhost:4200/skyrouter3/assets/vendor.js:49211:13)
    at get (http://localhost:4200/skyrouter3/assets/vendor.js:49194:14)
    at Class.get (http://localhost:4200/skyrouter3/assets/vendor.js:61084:34)"

Here's the full stack:


assert | @ | index.js:146
-- | -- | --
  | writableTag | @ | ember-metal.js:2911
  | tagFor | @ | ember-metal.js:1098
  | contentFor | @ | -proxy.js:21
  | unknownProperty | @ | -proxy.js:65
  | get | @ | ember-metal.js:3448
  | _getPath | @ | ember-metal.js:3463
  | get | @ | ember-metal.js:3446
  | get | @ | observable.js:38
  | (anonymous) | @ | controller.js:13
  | ComputedPropertyPrototype.get | @ | ember-metal.js:4067
  | get | @ | ember-metal.js:3439
  | compute | @ | ember-glimmer.js:325
  | value | @ | ember-glimmer.js:202
  | value | @ | runtime.js:161
  | initialize | @ | reference.js:390
  | peek | @ | reference.js:364
  | (anonymous) | @ | runtime.js:1067
  | evaluate | @ | runtime.js:44
  | evaluateSyscall | @ | runtime.js:3250
  | evaluateInner | @ | runtime.js:3226
  | evaluateOuter | @ | runtime.js:3218
  | next | @ | runtime.js:4800
  | execute | @ | runtime.js:4785
  | handleException | @ | runtime.js:4298
  | handleException | @ | runtime.js:4464
  | _throw | @ | runtime.js:4205
  | evaluate | @ | runtime.js:1098
  | execute | @ | runtime.js:4192
  | rerender | @ | runtime.js:4491
  | _this27.render | @ | ember-glimmer.js:4558
  | runInTransaction | @ | ember-metal.js:1231
  | _renderRoots | @ | ember-glimmer.js:4819
  | _renderRootsTransaction | @ | ember-glimmer.js:4851
  | _revalidate | @ | ember-glimmer.js:4891
  | invoke | @ | backburner.js:205
  | flush | @ | backburner.js:125
  | flush | @ | backburner.js:278
  | end | @ | backburner.js:410
  | _run | @ | backburner.js:760
  | _join | @ | backburner.js:736
  | join | @ | backburner.js:477
  | run.join | @ | ember-metal.js:456
  | hash.success | @ | rest.js:960
  | fire | @ | jquery.js:3268
  | fireWith | @ | jquery.js:3398
  | done | @ | jquery.js:9305
  | (anonymous) | @ | jquery.js:9548
  | load (async) |   |  
  | send | @ | jquery.js:9567
  | ajax | @ | jquery.js:9206
  | _ajaxRequest | @ | rest.js:982
  | (anonymous) | @ | rest.js:972
  | initializePromise | @ | rsvp.js:397
  | Promise | @ | rsvp.js:877
  | ajax | @ | rest.js:955
  | query | @ | rest.js:504
  | _query | @ | -private.js:8813
  | _query | @ | -private.js:10965
  | query | @ | -private.js:10952
  | afterModel | @ | route.js:20
  | applyHook | @ | router.js:211
  | runSharedModelHook | @ | router.js:662
  | runAfterModelHook | @ | router.js:646
  | tryCatcher | @ | rsvp.js:200
  | invokeCallback | @ | rsvp.js:372
  | publish | @ | rsvp.js:358
  | (anonymous) | @ | rsvp.js:14
  | invoke | @ | backburner.js:205
  | flush | @ | backburner.js:125
  | flush | @ | backburner.js:278
  | end | @ | backburner.js:410
  | _run | @ | backburner.js:760
  | _join | @ | backburner.js:736
  | join | @ | backburner.js:477
  | run.join | @ | ember-metal.js:456
  | hash.success | @ | rest.js:960
  | fire | @ | jquery.js:3268
  | fireWith | @ | jquery.js:3398
  | done | @ | jquery.js:9305
  | (anonymous) | @ | jquery.js:9548
  | load (async) |   |  
  | send | @ | jquery.js:9567
  | ajax | @ | jquery.js:9206
  | _ajaxRequest | @ | rest.js:982
  | (anonymous) | @ | rest.js:972
  | initializePromise | @ | rsvp.js:397
  | Promise | @ | rsvp.js:877
  | ajax | @ | rest.js:955
  | queryRecord | @ | rest.js:538
  | _queryRecord | @ | -private.js:8842
  | queryRecord | @ | -private.js:11063
  | model | @ | route.js:12
  | deserialize | @ | route.js:951
  | applyHook | @ | router.js:211
  | runSharedModelHook | @ | router.js:662
  | getModel | @ | router.js:896
  | tryCatcher | @ | rsvp.js:200
  | invokeCallback | @ | rsvp.js:372
  | publish | @ | rsvp.js:358
  | (anonymous) | @ | rsvp.js:14
  | invoke | @ | backburner.js:205
  | flush | @ | backburner.js:125
  | flush | @ | backburner.js:278
  | end | @ | backburner.js:410
  | _run | @ | backburner.js:760
  | _join | @ | backburner.js:736
  | join | @ | backburner.js:477
  | run.join | @ | ember-metal.js:456
  | (anonymous) | @ | has_element.js:18
  | exports.flaggedInstrument | @ | ember-metal.js:4580
  | handleEvent | @ | has_element.js:17
  | exports.default._emberMetal.Mixin.create._Mixin$create.handleEvent | @ | view_support.js:175
  | (anonymous) | @ | event_dispatcher.js:213
  | dispatch | @ | jquery.js:5183
  | elemData.handle | @ | jquery.js:4991


backspace added a commit to backspace/prison-rideshare-ui that referenced this issue May 9, 2019
These tests are producing the tag error discussed here:
emberjs/ember.js#16541

It looks to involve a rideProxy.distance access… I’m putting
it aside for now.
backspace added a commit to backspace/prison-rideshare-ui that referenced this issue May 10, 2019
This is a UX change to work around an instance of this error:
emberjs/ember.js#16541

Previously, the entire form showed before the user had chosen
a ride; now, the user has to choose a ride before the rest of
the form shows. I don’t love changing the UX as a workaround
for this error, but I couldn’t figure out another way.
@BryanCrotaz
Copy link

BryanCrotaz commented Jun 9, 2019

I'm seeing this in ember 3.8.3.

With @rwjblue 's unknownProperty fix it is intermittent but still happens about 1 in 5 runs.

I built an instance initializer:

import ObjectProxy from '@ember/object/proxy';

export function initialize(/* appInstance */) {
  ObjectProxy.reopen({
    unknownProperty(key) {
      if (this.isDestroying || this.isDestroyed) {
        return;
      }
      return this._super(key);
    },

    willWatchProperty(/*key*/) {
      if (this.isDestroying || this.isDestroyed ||
        this.content != null && 
        (this.content.isDestroying || this.content.isDestroyed)) {
        return;
      }
      return this._super(arguments);
    }
  });
}

export default {
  initialize
};

@BryanCrotaz
Copy link

Seems to work every time with

    unknownProperty(key) {
      if (this.isDestroying || this.isDestroyed) {
        return;
      }
      let content = this.content;
      if (content) {
        return get(content, key);
      }
    },

@AlexMayants
Copy link

We have encountered the same error as @BryanCrotaz in 3.8.3. I used a modified version of his solution:

    unknownProperty(key) {
      if (this.isDestroying || this.isDestroyed) {
        return;
      }

      let content = this.content;

      if (!content || content.isDestroying || content.isDestroyed) {
        return;
      }

      return this._super(key);
    },

It seems to work, but this should probably be fixed within the Ember core.

@Kilowhisky
Copy link

Just encountered this again on ember 3.19.0. @AlexMayants and @BryanCrotaz fixes appear to have worked.

DEBUG: -------------------------------
DEBUG: Ember : 3.19.0
DEBUG: Ember Data : 3.19.0
DEBUG: jQuery : 3.5.1
DEBUG: Ember Simple Auth : 3.0.0
DEBUG: Model Fragments : 5.0.0-beta.0
DEBUG: -------------------------------

backspace added a commit to hashicorp/nomad that referenced this issue Dec 15, 2020
This fixes an error:
“cannot create a new tag for (thing) after it has been destroyed”

Thanks to the suggestion here:
emberjs/ember.js#16541 (comment)
backspace added a commit to hashicorp/nomad that referenced this issue Jan 18, 2021
This fixes an error:
“cannot create a new tag for (thing) after it has been destroyed”

Thanks to the suggestion here:
emberjs/ember.js#16541 (comment)
backspace added a commit to hashicorp/nomad that referenced this issue Feb 2, 2021
This fixes an error:
“cannot create a new tag for (thing) after it has been destroyed”

Thanks to the suggestion here:
emberjs/ember.js#16541 (comment)
@al3xnag
Copy link

al3xnag commented Feb 21, 2022

octane version, otherwise autotracking is broken

    unknownProperty(key) {
      if (this.isDestroying || this.isDestroyed) {
        return;
      }

      let content = this.content;

-      if (!content || content.isDestroying || content.isDestroyed) {
+      if (content && (content.isDestroying || content.isDestroyed)) {
        return;
      }

      return this._super(key);
    },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants