Pass an Error to the callback instead of throw'ing

Throwing in an async handler results in an uncaught exception which
can never be handled by the consumer. Instead, invoke the callback
with an Error instance as the first argument (the callback is never
invoked with any arguments so this does not break the API).