The following principles should be used when writing error handling code:
Handle success / failure conditions before the stack clears. This means that any code that is asynchronous must catch exceptions just as it handles return value
Async code executed for side effect (e.g. upload a file) should handle exceptions and log error appropriately
HttpError error handlers send an http response
Non HttpError error handlers call next()
Define an subclass of Error for each error type
Use a helper function error() that takes an Error class and constructor arguments
Use a helper function assert() that takes a boolean and an Error object
I like the simplicity and readability of asserts. I think this will reduce cognitive load on us and potentially other developers that visit the GC code base.
WDYT about creating a GC errors library with common errors and translators as well as “helpers” for specific errors
Common errors
InvalidArgumentError
UnauthorizedError
IllegalStateError
The library would also have the common errors to Http response translator
This may be implied in what you wrote, but we might want to have a complete set of base classes that map out the space of possible handler actions, either with an http response or logging.
E.g. all errors that cause a 400 to be sent would inherit the Http400Error (class InvalidArgumentError extends Http400Error). Then we could check for those more abstract classes when handling errors.
From a DX perspective, this reduces error handling to defining an error class and writing an assert(). This will go along way to encouraging the creation of more detailed and descriptive error reporting.