Improve error handling

* Pass an error to the callback function
* Throw an error when the callback function throws an error
  or the callback is not a function