Unfortunately, like with setTimeout, the context in which a call was made is lost when using Meteor.defer. Which means that this will not contain the same things, and other methods like Meteor.user() won’t work as they need the context of a client initiated request to be able to access client specific variables like userId.
I’m unsure if the collection hooks have an impact of their own here as well.
You will either need to move the defer into the call, or extract the method into a server side only module and call that, passing in the userId. Definitely don’t pass userId into the methods method call. Allowing methods to accept userId as a parameter is dangerous as clients can then call the method pretending to be another user.
A question for someone familar with Meteor-core: is there a reason why Meteor.defer doesn’t automatically use Meter.bindEnvironment internally? Is there an overhead/downside to using it as standard?