Exception in callback of async function: undefined

I’ve been getting a bunch of errors in this format over the past few months:

Exception in callback of async function: undefined

This obviously makes it very hard to debug as I have no idea where the error is coming from and it’s a large application with different tasks running in the background fairly often.

Any idea why it happens, and how I can get a more descriptive error message? This error seems to happen in a bunch of places across the app.

Having a quick look where this message comes from takes me here:

Which is logged out of the logError function.
If we look up, where that’s called, we see it’s used in Meteor.wrapAsync when a callback was not provided to the wrapped function on the client (line 108).

So I would look for places where you’ve used Meteor.wrapAsync on the client, and called the wrapped function without a callback.
If you are able to replicate this locally, you can set a break point in the meteor.js pacakge file where logErr is called and explore up the call stack to find the offending function

The odd part is that it should only log if err is truthy, but your log says undefined? :man_shrugging:

It’s happening on the server. I also don’t see any usage of wrapAsync in my code directly. May be another function that’s calling it.

What Meteor version?

Okay, taking another look, I found this, which has that extra : on the end and runs on the server:

This time it’s in the definition of Meteor.bindEnvironment. So that’s the next thing to search for.

This one doesn’t check if an error was passed in before logging, which also matches the log you quoted. Just need to work out which function isn’t throwing an error!

If you want to put a breakpoint here and track down which function threw the error, it’s going to be a bit harder. The packaged code does end up in .meteor/local/build/programs/server/packages/meteor.js, so you can probably drop a debugger statement in there and run your app with the --inspect flag.
Alternatively, make your own stack trace by logging a new Error on that line

So I managed to reproduce it by throwing an error inside a callback of HTTP.get callback inside of a Meteor method call (although I feel like this happens for many sorts of errors in our system). Will try dig into deeper now

Meteor version: METEOR@1.8.1

So it’s pretty easy to reproduce with setTimeout. A Meteor method that has a setTimeout that throws will do this. For example:

  myMethod() {
    Meteor.setTimeout(() => {
      throw new Meteor.Error('xyz');
    }, 100);

And throw:

Exception in setTimeout callback: undefined

At least I know it’s setTimeout in this exception, although undefined message makes it pretty hard to track down if you don’t know where it’s coming from. The async function: undefined error is even worse.

1 Like

hmmm, I’m think it just doesn’t like it when a method throws after it’s already returned to the client.
On the server, HTTP.get doesn’t need a callback, but if it’s a shared method, that’s not an option.
You could promisify the method and return a promise instead?

I am facing the same issue because I have try/catch blocks where I don’t want the error being thrown to interfere in the main thread. My hope with the code below is that the error would be printed in the console and still be caught by my error reporting tool

  try {
    throw new Error('FOO') // error that I don't want to block the main thread
  } catch (e) {
    console.log(e); // logging that works fine

    Meteor.setTimeout(() => {
      throw e; // error that is not handled as expected

Has anyone had any luck with this? We’ve seen the log message a lot recently on our server but can’t reproduce it locally so are a bit stumped as to how to find it. My hunch is that it emanates from the function dontBindEnvironment used by the Hook class.

Likely sources then might be DDP._reconnectHook and AccountsServer._validateLoginHook as they don’t specify debugPrintExceptions which would change the error printed. The reconnect hook is on the client though so that rules that out but we do have quite a lot of code added via Accounts.validateLoginAttempt . I’ve checked it though and can’t find anything async :thinking:

From what I’ve seen in development it can happen all over the place.

Http.get being one example, but it happens all over.

Yeah, we do have one HTTP.get inside our validateLoginHook but it’s not async…

Still searching :mag: