4

I have a situation where a user may provide bad data to get to a datapoint that may not exist. Currently, the error types raised when these problems happen is not clear or straightforward.

In my API, I intend to create a error to catch in the UI (or I'll let the UI framework handle it by reporting it straight to the user, which I've tested and know works.):

class DataError(ValueError):
    '''
    raise this error with a message of what was wrong, 
    will also be caught when catching general ValueErrors
    or other Exceptions that ValueError subclasses
    '''

And usage:

if user_input not in accepted_values:
    raise DataError('bad user_input: {0}'.format(user_input))

I do get rather opinionated about my approach, and I want rather unassailable code. I'm aware of the upsides, as I can catch this specific exception without hiding others. But I can't think of any downsides.

What are the downsides of doing this as opposed to just raising my error message with ValueError?

4
  • 1
    More work for you to create the new exception type? Aside from that, I think creating more specific exception types for your applications is always a good idea. Though I guess it could be considered redundant if no user would ever want to treat a DataError differently from a ValueError. Commented Jul 24, 2014 at 19:58
  • 1
    No real downside if you ask me, this is exactly the way to go. Specific exceptions make for much more meaningful tracebacks (and code) than generic ones. For an example of a popular library that does it exactly like this, see requests.exceptions. Commented Jul 24, 2014 at 20:16
  • Also see SQLAlchemy (code / docs) for some well thought-out exception design. Incidentally also lists a DataError. If it's good enough for Mike, it's good enough for me. Commented Jul 24, 2014 at 20:29
  • It's a bit of code maintenance burden. That's about it. Apart from that, the maxim of "always catch the narrowest possible exception" is a good one to follow, and making custom exceptions helps with that. Commented Jul 24, 2014 at 20:41

2 Answers 2

4

Writing custom exceptions is almost always the right thing to do. With that said, there are a few minor potential downsides to subclassing an exception:

  1. Does your error correspond exactly to an error in the standard library? For example, implementing an object that looks like a dict, you just want to throw KeyError.

  2. Are you subclassing the right thing? In your example, anyone catching ValueError will also catch DataError. Depending on your use case, there may be times where this isn't appropriate.

  3. Does the exception you are subclassing provide additional functionality? It's a class, it may have all sorts of methods. If you subclass an exception, you ought to verify that all its methods make sense for your error situation.

In other circumstances, an exception may not be appropriate at all. Is there an 'no value' result (e.g. None or []) that would be more suitable?

Sign up to request clarification or add additional context in comments.

1 Comment

1) No. 2) Yes. 3) No. But thanks for the answer, these are potential downsides! Plus one to you!
3

I am a fan of custom exceptions. The downside of using the ValueError and your error message is that for you catch this specific error, you also have to do some string matching, instead of just catching your custom exception. Raising a subclass of ValueError makes it easier to see that there is a bug in the implementation.

Additionally, ValueError is fairly vague in what it actually covers.

Raised when a built-in operation or function receives an argument that has the right type but an inappropriate value, and the situation is not described by a more precise exception

Presumably, your DataError has a well defined range of valid values. In that case, it is definitely more appropriate as it is more specific.

1 Comment

Thanks for the feedback, you're assisting my confirmation bias, but I really was trying to get some sort of firm downside.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.