How to fix Meteor JS Error "Exception from Meteor.flush ... firstNode"
Developing on the Meteor JavaScript platform has been great, but we ran into a frustrating issue with Meteor's rendering engine, Spark. We were getting the following error:
Exception from Meteor.flush: TypeError: Cannot call method 'firstNode' of undefined at Object.Spark.renderToRange (http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:545:25) at http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:860:13 at http://localhost:3000/packages/deps/deps-utils.js?f3fceedcb1921afe2b17e4dbd9d4c007f409eebb:78:31 at _.extend.run (http://localhost:3000/packages/deps/deps.js?1df0a05d3ec8fd21f591cfc485e7b03d2e2b6a01:19:20) at rerun (http://localhost:3000/packages/deps/deps-utils.js?f3fceedcb1921afe2b17e4dbd9d4c007f409eebb:78:11) at _.extend.onInvalidate (http://localhost:3000/packages/deps/deps.js?1df0a05d3ec8fd21f591cfc485e7b03d2e2b6a01:42:9) at rerun (http://localhost:3000/packages/deps/deps-utils.js?f3fceedcb1921afe2b17e4dbd9d4c007f409eebb:79:11) at Object.Meteor.autorun (http://localhost:3000/packages/deps/deps-utils.js?f3fceedcb1921afe2b17e4dbd9d4c007f409eebb:81:5) at Object.Spark.isolate (http://localhost:3000/packages/spark/spark.js?c202b31550c71828e583606c7a5e233ae9ca50e9:840:10) at http://localhost:3000/packages/templating/deftemplate.js?91fdd4353cca922f7a59ff593d000211c2857c84:134:28 logging.js:30
After some back and forth on IRC and an e-mail thread with Meteor Development Group developer David Greenspan, we tracked down the cause. As usual, it was a bug in the code.
So what was the bug in Meteor JS?
It was pretty straightforward, actually; we were calling
Session.setfrom within a reactive context. There were also code paths where we were calling
Session.getfor the same variable. In other words:
We were getting a cross between a race condition and an infinite loop. That's basically the way I understood it. The reactive context was changing the basis for the reactive context, which would then do the same thing, ad infinitum.
We moved the Session.set calls to event handlers instead, and we were good. One can also use
Meteor.autorunas long as you don't add a dependency on the variable you're setting. So you can do
Session.set('some_variable', 'some_value')as long as you don't
Session.get('some_variable')within the same block.
Meteor.startupis also an appropriate place for stuff you want to initialize very early in the app. Keep in mind that the app won't know if users are logged in or not yet. You should add a
Meteor.autoruncall that reacts to
Meteor.userId(and potentially
Meteor.loggingInif that's what you're after.)