Meteor 1.3 user undefined

Since upgrading to Meteor 1.3, I’ve had a bit of a problem getting the user’s profile in template.autorun. Here’s my code:

Template.dashboard.onCreated(function() {
  var self = this;
  self.autorun(function() {
    var orgId = Meteor.user().profile.currentOrg;
    self.subscribe('tasks', orgId);
  });
});

And here’s the error:

Exception in defer callback: TypeError: Cannot read property 'profile' of undefined
    at .<anonymous> (http://localhost:3000/app/app.js?hash=bbf512fa5c5ae71422836031aeccf663a1243196:5826:30)
    at http://localhost:3000/packages/blaze.js?hash=38069f4f7cfbd8898160bc97d37dd847cd5985fe:1865:20
    at Function.Template._withTemplateInstanceFunc (http://localhost:3000/packages/blaze.js?hash=38069f4f7cfbd8898160bc97d37dd847cd5985fe:3677:12)
    at http://localhost:3000/packages/blaze.js?hash=38069f4f7cfbd8898160bc97d37dd847cd5985fe:1863:29
    at Object.Blaze._withCurrentView (http://localhost:3000/packages/blaze.js?hash=38069f4f7cfbd8898160bc97d37dd847cd5985fe:2204:12)
    at viewAutorun (http://localhost:3000/packages/blaze.js?hash=38069f4f7cfbd8898160bc97d37dd847cd5985fe:1862:18)
    at Tracker.Computation._compute (http://localhost:3000/packages/tracker.js?hash=b267c37effdf4af331d16fc647c0370c2eaff44d:341:36)
    at new Tracker.Computation (http://localhost:3000/packages/tracker.js?hash=b267c37effdf4af331d16fc647c0370c2eaff44d:229:10)
    at Object.Tracker.autorun (http://localhost:3000/packages/tracker.js?hash=b267c37effdf4af331d16fc647c0370c2eaff44d:580:11)
    at Blaze.View.autorun (http://localhost:3000/packages/blaze.js?hash=38069f4f7cfbd8898160bc97d37dd847cd5985fe:1875:22)

Why would Meteor.user() be undefined?

If I refresh, I can get the page to render normally, but this makes me a little nervous to push it to production. Any ideas?

Maybe a race condition because the user is not available yet when the dashboard is being initialized. Normally, this should only happen if you reload the browser.

As a workaround, I’d just write it this way:

Template.dashboard.onCreated(function() {
  const self = this;
  self.autorun(function() {
    const user = Meteor.user();
    if (!user) {
       return;
    }
    const orgId = user.profile.currentOrg;
    self.subscribe('tasks', orgId);
  });
});

Since user() is reactive, the autorun would re-run once the user is available.

Another option would be:

Template.dashboard.onCreated(function() {
  const self = this;
  self.autorun(function() {
    const orgId = ((Meteor.user() || {}).profile || {}).currentOrg;
    self.subscribe('tasks', orgId);
  });
});

But this is not as explicit as the version above and maybe not as “readable”.

2 Likes

This is definitely a race condition and should have occurred randomly in previous versions as well. In production this would most likely happen every time since the network latency would be much higher. A nice fix is adding the meteorhacks:fast-render package. This will make the signed in user available on page load due to it sending down all null publications with the initial HTML of the page.

2 Likes

@waldgeist and @copleykj – thanks very much for the feedback! I ended up solving it like this:

Template.dashboard.onCreated(function() {
  const self = this;
  self.autorun(function() {
    const orgId = Meteor.user() && Meteor.user().profile.currentOrg;
    self.subscribe('tasks', orgId);
  });
});

So strange that it didn’t appear until I upgraded to 1.3, but it appears it was a race condition and just adding Meteor.user() && to the constant fixed it.

Thanks again!

1 Like