Skip to content

Instantly share code, notes, and snippets.

@smithamax
Last active August 6, 2021 06:21
Show Gist options
  • Save smithamax/31bd849081e44fb2b5eb391a465b3e6d to your computer and use it in GitHub Desktop.
Save smithamax/31bd849081e44fb2b5eb391a465b3e6d to your computer and use it in GitHub Desktop.
Error patterns

Do's

Don't catch errors in the first place

Not catching an error is perfectly fine, if it's something that shouldn't happen just let it fall through and cause a 500 so we know to fix it

Mapping errors

Most of the time when you catch an error you want to map from an infrastructure error (sql, http, rabbit) to a domain error, note this should be done in the infrastructure layer, the domain shouldn't know about the implementation details

try {
    throwyThing();
} catch (err) {
    switch err.code {
        case "123":
            throw new NotFoundError("Some message")
        case "456":
            throw new ValidationError(err.message)
        default:
            throw err
    }
}

Mapping errors, log and throw the unknown case

Sometimes you might want to just squash all upstream errors and log all the details This can be useful for third parties where you don't know all the errors that could happen but you do know where you want to map them

Downstream you'll just get a generic Unknown "thing" error but you'll know that means there is an unhandled case

try {
    await ACMI.fetchProduct();
} catch (err) {
    switch err.code {
        case "123":
            throw new NotFoundError("Couln't find the product")
        default:
            logger.error(`Unknown ACMI error code=${err.code}, err=${err}`)
            throw new UnknownACMIError("Unknown ACMI error");
    }
}

Don'ts

catch and throw new error

If all you do is catch and throw a new error using the existing message, all you're doing is squashing the stack trace and no value is added

try {
    throwyThing();
} catch (err) {
   throw new Error(err.message);
}

log and rethrow

Logging errors for the most part should only happen at the application boundaries for example the http/graphql logger, you shouldn't need to log and rethrow unless you're debugging

For example in most cases this will result in double logging

try {
    throwyThing();
} catch (err) {
   logger.error(err.message)
   throw err;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment