Related
Say I have a web application with UserController. Client sends a HTTP POST request that is about to be handled by the controller. That however first must parse the provided json to UserDTO. For this reason there exist a UserDTOConverter with a method toDTO(json): User.
Given I value functional programming practices for its benefits of referential transparency and pure function the question is. What is the best approach to deal with a possibly inparsable json? First option would be to throw an exception and have it handled in global error handler. Invalid json means that something went terrible wrong (eg hacker) and this error is unrecoverable, hence the exception is on point (even assuming FP). The second option would be to return Maybe<User> instead of User. Then in the controller we can based on the return type return HTTP success response or failure response. Ultimately both approaches results in the same failure/success response, which one is preferable though?
Another example. Say I have a web application that needs to retrieve some data from remote repository UserRepository. From a UserController the repository is called getUser(userId): User. Again, what is the best way to handle the error of possible non existent user under provided id? Instead of returning User I can again return Maybe<User>. Then in controller this result can be handled by eg returning "204 No Content". Or I could throw an exception. The code stays referentially transparent as again I am letting the exception to bubble all the way up to global error handler (no try catch blocks).
Whereas in the first example I would lean more towards throwing an exception in the latter one I would prefer returning a Maybe. Exceptions result in cleaner code as the codebase is not cluttered with ubiquitous Eithers, Maybes, empty collections, etc. However, returning these kinds of data structure ensure explicitness of the calls, and imo results in better discoverability of the error.
Is there a place for exceptions in functional programming? What is the biggest pitfall of using exceptions over returning Maybes or Eithers? Does it make sense to be throwing exceptions in FP based app? If so is there a rule of thumb for that?
TL;DR
If there are Maybes/Eithers all over the codebase, you generally have a problem with I/O being mixed promiscuously with business logic. This doesn't get any better if you replace them with exceptions (or vice versa).
Mark Seemann has already given a good answer, but I'd like to address one specific bit:
Exceptions result in cleaner code as the codebase is not cluttered with ubiquitous Eithers, Maybes, empty collections, etc.
This isn't necessarily true. Either part.
Problem with Exceptions
The problem with exceptions is that they circumvent the normal control flow, which can make the code difficult to reason about. This seems so obvious as to barely be worthy of mention, until you end up with an error thrown 20 calls deep in a call stack where it isn't clear what triggered the error in the first place: even though the stack trace might point you to the exact line in the code you might have a very hard time figuring out the application state that caused the error to happen. The fact that you can be undisciplined about state transitions in an imperative/procedural program is of course the whole thing that FP is trying to fix.
Maybe, Maybe not: It might be Either one
You shouldn't have ubiquitous Maybes/Eithers all over the codebase, and for the same reason that you shouldn't be throwing exceptions willy-nilly all over the codebase: it complicates the code too much. You should have files that are entry points to the system, and those I/O-concerned files will be full of Maybes/Eithers, but they should then delegate to normal functions that either get lifted or dispatched to through some other mechanism depending on language (you don't specify the language). At the very least languages with option types almost always support first-class functions, you can always use a callback.
It's kind of like testability as a proxy for code quality: if your code is hard to test it probably has structural problems. If your codebase is full of Maybes/Eithers in every file it probably has structural problems.
You're asking about a couple of different scenarios, and I'll try to address each one.
Input
The first question pertains to converting a UserDTO (or, in general, any input) into a stronger representation (User). Such a conversion is usually self-contained (has no external dependencies) so can be implemented as a pure function. The best way to view such a function is as a parser.
Usually, parsers will return Either values (AKA Result), such as Either<Error, User>. The Either monad is, however, short-circuiting, meaning that if there's more than one problem with the input, only the first problem will be reported as an error.
When validating input, you often want to collect and return a list of all problems, so that the client can fix all problems and try again. A monad can't do that, but an applicative functor can. In general, I believe that validation is a solved problem.
Thus, you'll need to model validation as a type that isomomorphic to Either, but has different applicative functor behaviour, and no monad interface. The above links already show some examples, but here's a realistic C# example: An applicative reservation validation example in C#.
Data access
Data access is different, because you'd expect the data to already be valid. Reading from a data store can, however, 'go wrong' for two different reasons:
The data is not there
The data store is unreachable
The first issue (querying for missing data) can happen for various reasons, and it's usually appropriate to plan for that. Thus, a database query for a user should return Maybe<User>, indicating to the client that it should be ready to handle both cases: the user is there, or the user is not there.
The other issue is that the data store may sometimes be unreachable. This can be caused by a network partition, or if the database server is experiencing problems. In such cases, there's usually not much client code can do about it, so I usually don't bother explicitly modelling those scenarios. In other words, I'd let the implementation throw an exception, and the client code would typically not catch it (other than to log it).
In short, only throw exceptions that are unlikely to be handled. Use sum types for expected errors.
I have seen code like below, where exceptions are wrapped in a generic error. What i don't like about this approach is that we need to write a handler to deal with this UnexpectedError, inspect it, extract the exception and log it. Not sure if this is the correct way to do it.
override suspend fun update(
reservation: Reservation,
history: ReservationHistory
): Either<ReservationError, Reservation> {
return Either.catch {
mongoClient.startSession().use { clientSession ->
clientSession.startTransaction()
mongoClient.getDatabase(database)
.getCollection<ReservationDocument>()
.updateOneById(reservation.reservationId.value, MapToReservationDocument.invoke(reservation))
mongoClient.getDatabase(database)
.getCollection<ReservationHistoryDocument>()
.insertOne(MapToReservationHistoryDocument.invoke(history))
reservation
}
}.mapLeft {
UnexpectedError(it)
}
}
I see a lot of code written where an exception is thrown if a parameter is not in the right form, or whatever. Basically "throw new ...".
What is the benefit of this? The exception can be avoided by checking the parameters (Eg if null, write message back to webpage/winform). Why is this approach not used when an exception is expensive?
Thanks
A few points are worth making here:
First, your supposition that exceptions are expensive is generally untrue - exceptions are, well ... exceptional. They shouldn't be occurring often enough to have any meaningful effect on program performance. And if you are seeing enough exceptions that performance is a problem then you have bigger fish to fry.
Second, a well written class, function or module program should be able to detect and handle invalid input somewhat gracefully. It helps the maintainers and debuggers of the code locate the problems as close to their introduction as possible. If arguments are not checked, they can often result in a failure much later in the code - far removed from the actual error. Debugging such problems can be very painful.
Third, you assume that all code is aware of the context in which it is executed. A method may be deep in a framework or library and have no knowledge of whether it is running in a web application, console app, NT service, etc. Besides, it'a terrible practice to pepper logic to display information about invalid arguments throughout the body of your code - that responsibility should be centralized and controlled - otherwise you UI could easily become a mess of errors interspersed with actual presentation content.
Finally, exceptions allow a program to sometimes handle and recover from a problem rather than exposing it to the user. Don't diminish this capability by directly displaying errors immediately when they occur. Now, granted, most often invalid arguments are a symptom of a programming defect (rather than an environmental or configuration issue) - and so in most cases they can't be handled. But, then again, sometimes they can be handled.
For example, if you're writing a library to be used by code you don't know about or doesn't exist yet, how that error is handled is down to the code that is making the call.
So throwing an exception is a natural thing to do. Allows you to leave the decision on how to handle that error scenario to the caller/consumer.
Throwing an exception:
makes it clear to other programmers that the situation is exceptional
allows software calling the method involved to clearly handle the problem
shows tools and the compiler that the situation is exceptional so that they can assist the programmer
allows information to be passed to handling routines in the exception object itself
Printing strings - well - doesn't, really.
In terms of the 'expense' of an exception, exceptions should only be thrown in exceptional circumstances, i.e. rarely and as part of processing errors - I personally have not come across a situation where the 'expense' of an exception is a problem. More discussion on that point in this question.
This is known as Design by Contract.
The basic idea of Design by Contract is that objects have contracts between them, and if a caller does not fulfill the contract the receiver should fail with an exception rather than trying to guess the callers intention. At the end of the day, this leads to more stable software (in particular when more than one person is writing on project, since then the contract also become contracts between programmers).
PS: An important issue of Design by Contract that is often forgotten is the following. It must be possible for the client to know whether it fulfills the contract or not. So eg, if the contract of a stack is that client may only pop when the stack is not empty there must be an isEmpty method to check that and clients should use that method before calling pop. So this is why code that uses Design by Contract is cluttered with exceptions that are nevertheless never thrown.
It is better to throw an exception if the code will be compiled into a library and reused in multiple applications. In that case the client that calls into the library should handle the exceptions appropriately and report a user friendly message.
There are two main reasons I throw exceptions instead of writing an error message to standard out.
Debugging is easier - I know if the program has exited because of an error. Also, since exceptions in Java can be subclassed, I know exactly what type of error has occurred.
If you write an API, and then decide you want a GUI front-end, perhaps you want to take those exceptions and display them in a message dialog instead of writing them to standard out.
Generally and language-agnostically speaking, it is not correct assumption that exceptions are expensive. It depends on many factors.
Generally, exception is a generic way to signal an error condition and it is independent of any form of presentation. Sending out a page with error message would make the error reporting too tightly coupled with presentation, with UI. It is usually not a good idea in terms of flexible and scalable design.
The question is general and language-agnostic, thus the answer does not go deeply into details.
By the way, depending on a programming language, design of error handling, and number of other factors, approaches can be different. However, it's a good idea to learn about various options:
in C++, in Boost project, error handling guidelines say:
Don't worry too much about the what()
message. It's nice to have a message
that a programmer stands a chance of
figuring out, but you're very unlikely
to be able to compose a relevant and
user-comprehensible error message at
the point an exception is thrown (...)
Krzysztof Cwalina recommends a set of very useful Design Guidelines for .NET but they are in fact language-agnostic like Should Exceptions Carry Error Code Information
Given the guidelines above, after a while of consideration, it is not that clear what such error web page should display, what level of information, very technical or more user-friendly. Using exceptions, it gives more flexibility on various levels of the system as one of rules it catch when you need to handle (i.e. display error) ignore otherwise
Exceptions are, in most environments, easier to write tests for than is stuff written to the console:
it "should reject a negative initial balance" do
Account.new(-1).should raise_error(ArgumentError, "Invalid balance: -1")
end
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
Improve this question
Yesterday I was having a heated debate with a coworker on what would be the preferred error reporting method. Mainly we were discussing the usage of exceptions or error codes for reporting errors between application layers or modules.
What rules do you use to decide if you throw exceptions or return error codes for error reporting?
In high-level stuff, exceptions; in low-level stuff, error codes.
The default behaviour of an exception is to unwind the stack and stop the program, if I'm writing a script an and I go for a key that's not in a dictionary it's probably an error, and I want the program to halt and let me know all about that.
If, however, I'm writing a piece of code which I must know the behaviour of in every possible situation, then I want error codes. Otherwise I have to know every exception that can be thrown by every line in my function to know what it will do (Read The Exception That Grounded an Airline to get an idea of how tricky this is). It's tedious and hard to write code that reacts appropriately to every situation (including the unhappy ones), but that's because writing error-free code is tedious and hard, not because you're passing error codes.
Both Raymond Chen and Joel have made some eloquent arguments against using exceptions for everything.
I normally prefer exceptions, because they have more contextual information and can convey (when properly used) the error to the programmer in a clearer fashion.
On the other hand, error codes are more lightweight than exceptions but are harder to maintain. Error checking can inadvertently be omitted. Error codes are harder to maintain because you have to keep a catalog with all error codes and then switch on the result to see what error was thrown. Error ranges can be of help here, because if the only thing we are interested in is if we are in the presence of an error or not, it is simpler to check (e.g., an HRESULT error code greater or equal to 0 is success and less than zero is failure). They can inadvertently be omitted because there is no programmatic forcing that the developer will check for error codes. On the other hand, you cannot ignore exceptions.
To summarize I prefer exceptions over error codes in almost all situations.
I prefer exceptions because
they interupt the flow of logic
they benefit from class hierarchy which gives more features/functionality
when used properly can represent a wide range of errors (e.g. an InvalidMethodCallException is also a LogicException, as both occur when there's a bug in your code that should be detectable before runtime), and
they can be used to enhance the error (i.e. a FileReadException class definition can then contain code to check whether the file exists, or is locked, etc)
Error codes can be ignored (and often are!) by the callers of your functions. Exceptions at least force them to deal with the error in some way. Even if their version of dealing with it is to have an empty catch handler (sigh).
Exceptions over error codes, no doubt about it. You get much of the same benefits from exceptions as you do with error codes, but also much more, without the shortcomings of error codes. The only knock on exceptions is that it is slightly more overhead; but in this day and age, that overhead should be considered negligible for nearly all applications.
Here are some articles discussing, comparing and contrasting the two techniques:
Object Oriented Exception Handling in Perl
Exceptions vs. status returns
There are some good links in those that can give you further reading.
I would never mix the two models...it's too hard to convert from one to the other as you move from one part of the stack which is using error codes, to a higher piece that is using exceptions.
Exceptions are for "anything that stops or inhibits the method or subroutine from doing what you asked it to do" ... NOT to pass messages back about irregularities or unusual circumstances, or the state of the system, etc. Use return values or ref (or out) parameters for that.
Exceptions allow methods to be written (and utilized) with semantics that are dependent on the method's function, i.e. a method that returns an Employee object or List of Employees can be typed to do just that, and you can utilize it by calling.
Employee EmpOfMonth = GetEmployeeOfTheMonth();
With error codes, all methods return an error code, so, for those that need to return something else to be used by the calling code, you have to pass a reference variable to be populated with that data, and test the return value for the error code, and handle it, on every function or method call.
Employee EmpOfMonth;
if (getEmployeeOfTheMonth(ref EmpOfMonth) == ERROR)
// code to Handle the error here
If you code so that each method does one and only one simple thing, then you should throw an exception whenever the method cannot accomplish the method's desired objective. Exceptions are much richer and easier to use in this way than error codes. Your code is much cleaner - The standard flow of the "normal" code path can be devoted strictly to the case where the method IS able to accomplish what you wanted it to do... And then the code to clean up, or handle the "exceptional" circumstances when something bad happens that prevents the method from completing successfully can be siloed away from the normal code. Additionally, if you can't handle the exception where it occurred, and must pass it up the stack to a UI, (or worse, across the wire from a mid-tier component to a UI), then with the exception model, you don't need to code every intervening method in your stack to recognize and pass the exception up the stack... The exception model does this for you automagically.... With error codes, this piece of the puzzle can get onerous very rapidly.
You should use both. The thing is to decide when to use each one.
There are a few scenarios where exceptions are the obvious choice:
In some situations you can't do anything with the error code, and you just need to handle it in an upper level in the call stack, usually just log the error, display something to the user or close the program. In these cases, error codes would require you to bubble up the error codes manually level by level which is obviously much easier to do with exceptions. The point is that this is for unexpected and unhandleable situations.
Yet about situation 1 (where something unexpected and unhandleable happens you just wan't to log it), exceptions can be helpful because you might add contextual information. For example if I get a SqlException in my lower-level data helpers, I will want to catch that error in the low-level (where I know the SQL command that caused the error) so I can capture that information and rethrow with additional information. Please note the magic word here: rethrow, and not swallow.
The first rule of exception handling: do not swallow exceptions. Also, note that my inner catch doesn't need to log anything because the outer catch will have the whole stack trace and may log it.
In some situations you have a sequence of commands, and if any of them fail you should cleanup/dispose resources(*), whether or not this is an unrecoverable situation (which should be thrown) or a recoverable situation (in which case you can handle locally or in the caller code but you don't need exceptions). Obviously it's much easier to put all those commands in a single try, instead of testing error codes after each method, and cleanup/dispose in the finally block. Please note that if you want the error to bubble up (which is probably what you want), you don't even need to catch it - you just use the finally for cleanup/dispose - you should only use catch/retrow if you want to add contextual information (see bullet 2).
One example would be a sequence of SQL statements inside a transaction block. Again, this also a "unhandleable" situation, even if you decide to catch it early (treat it locally instead of bubbling up to the top) it's still a fatal situation from where the best outcome is to abort everything or at least abort a large part of the process.
(*) This is like the on error goto that we used in old Visual Basic
In constructors you can only throw exceptions.
Having said that, in all other situations where you're returning some information on which the caller CAN/SHOULD take some action, using return codes is probably a better alternative. This includes all expected "errors", because probably they should be handled by the immediate caller, and will hardly need to be bubbled up too many levels up in the stack.
Of course it's always possible to treat expected errors as exceptions, and catch then immediately one level above, and it's also possible to encompass every line of code in a try catch and take actions for each possible error. IMO, this is bad design, not only because it's much more verbose, but specially because the possible exceptions that might be thrown are not obvious without reading the source code - and exceptions could be thrown from any deep method, creating invisible gotos. They break code structure by creating multiple invisible exit points that make code hard to read and inspect. In other words, you should never use exceptions as flow-control, because that would be hard for others to understand and maintain. It can get even difficult to understand all possible code flows for testing.
Again: for correct cleanup/dispose you can use try-finally without catching anything.
The most popular criticism about return codes is that "someone could ignore the error codes, but in the same sense someone can also swallow exceptions. Bad exception handling is easy in both methods. But writing good error-code-based program is still much easier than writing an exception-based program. And if one by any reason decides to ignore all errors (the old on error resume next), you can easily do that with return codes and you can't do that without a lot of try-catchs boilerplate.
The second most popular criticism about return codes is that "it's difficult to bubble up" - but that's because people don't understand that exceptions are for non-recoverable situations, while error-codes are not.
Deciding between exceptions and error codes is a gray area. It's even possible that you need to get an error code from some reusable business method, and then you decide to wrap that into an exception (possibly adding information) and let it bubble up. But it's a design mistake to assume that ALL errors should be thrown as exceptions.
To sum it up:
I like to use exceptions when I have an unexpected situation, in which there's not much to do, and usually we want to abort a large block of code or even the whole operation or program. This is like the old "on error goto".
I like to use return codes when I have expected situations in which the caller code can/should take some action. This includes most business methods, APIs, validations, and so on.
This difference between exceptions and error codes is one of the design principles of the GO language, which uses "panic" for fatal unexpected situations, while regular expected situations are returned as errors.
Yet about GO, it also allows multiple return values , which is something that helps a lot on using return codes, since you can simultaneously return an error and something else. On C#/Java we can achieve that with out parameters, Tuples, or (my favorite) Generics, which combined with enums can provide clear error codes to the caller:
public MethodResult<CreateOrderResultCodeEnum, Order> CreateOrder(CreateOrderOptions options)
{
....
return MethodResult<CreateOrderResultCodeEnum>.CreateError(CreateOrderResultCodeEnum.NO_DELIVERY_AVAILABLE, "There is no delivery service in your area");
...
return MethodResult<CreateOrderResultCodeEnum>.CreateSuccess(CreateOrderResultCodeEnum.SUCCESS, order);
}
var result = CreateOrder(options);
if (result.ResultCode == CreateOrderResultCodeEnum.OUT_OF_STOCK)
// do something
else if (result.ResultCode == CreateOrderResultCodeEnum.SUCCESS)
order = result.Entity; // etc...
If I add a new possible return in my method, I can even check all callers if they are covering that new value in a switch statement for example. You really can't do that with exceptions. When you use return codes, you'll usually know in advance all possible errors, and test for them. With exceptions you usually don't know what might happen. Wrapping enums inside exceptions (instead of Generics) is an alternative (as long as it's clear the type of exceptions that each method will throw), but IMO it's still bad design.
EDIT 2020-10-11:
Since C# 7.0 (March 2017) instead of Generics I prefer to use the new Tuples syntax which allows multiple return values (so we can use GO-like syntax where methods return a result OR an error).
public enum CreateUserResultCodeEnum
{
[Description("Username not available")]
NOT_AVAILABLE,
}
public (User user, CreateUserResultCodeEnum? error) CreateUser(string userName)
// (try to create user, check if not available...)
if (notAvailable)
return (null, CreateUserResultCodeEnum.NOT_AVAILABLE);
return (user, null);
}
// How to call and deconstruct tuple:
(var user, var error) = CreateUser("john.doe");
if (user != null) ...
if (error == CreateUserResultCodeEnum.NOT_AVAILABLE) ...
// Or returning a single object (named tuple):
var result = CreateUser("john.doe");
if (result.user != null) ...
if (result.error == CreateUserResultCodeEnum.NOT_AVAILABLE) ...
EDIT 2021-01-09:
A few days ago I wrote this blog post about how we can (in some cases!) use multiple returns instead of exceptions (like golang convention explained above, not supposed to replace all your exceptions but supposed to give you arsenal to decide between when to use exceptions and when to use return codes).
By the end of the post I'm mixing two models - basically I'm using the ValueTuple syntax (which is very concise and elegant) but yet using Generics as the underlying structure.
Basically I use implicit conversion operator and type deconstructors to convert back and forth between ValueTuple and CommandResult<TEntity, TError>.
In the past I joined the errorcode camp (did too much C programming). But now I have seen the light.
Yes exceptions are a bit of a burden on the system. But they simplify the code, reducing the number of errors (and WTF's).
So use exception but use them wise. And they will be your friend.
As a side note. I have learned to document which exception can be thrown by which method. Unfortunately this is not required by most languages. But it increases the chance of handling the right exceptions at the right level.
There may be a few situations where using exceptions in a clean, clear, correct way is cumbersome, but the vast majority of the time exceptions are the obvious choice. The biggest benefit exception handling has over error codes is that it changes the flow of execution, which is important for two reasons.
When an exception occurs, the application is no longer following it's 'normal' execution path. The first reason why this is so important is that unless the author of the code goes well and truly out of their way to be bad, the program will halt and not continue doing unpredictable things. If an error code doesn't get checked and appropriate actions aren't taken in response to a bad error code, the program will keep on doing what it's doing and who knows what the result of that action will be. There are lots of situations where having the program do 'whatever' could wind up being very expensive. Consider a program that retrieves performance information for various financial instruments a company sells, and delivers that information to brokers/wholesalers. If something goes wrong and the program keeps going, it could ship erroneous performance data to the brokers and wholesalers. I don't know about anybody else, but I don't want to be the one sitting in a VPs office explaining why my code caused the company to get 7-figures worth of regulatory fines. Delivering an error message to customers is generally preferable to delivering wrong data that could look to be 'real', and the latter situation is much easier to run into with a much less aggressive approach like error codes.
The second reason why I like exceptions and their breaking of the normal execution is that it makes it much, much easier to keep the 'normal things are happening' logic separate from the 'something went wrong logic'. To me, this:
try {
// Normal things are happening logic
catch (// A problem) {
// Something went wrong logic
}
...is preferable to this:
// Some normal stuff logic
if (errorCode means error) {
// Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
// Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
// Some stuff went wrong logic
}
There are other little things about exceptions that are nice, as well. Having a bunch of conditional logic to keep track of whether any of the methods being called in a function had an error code returned, and return that error code higher up is a lot of boiler plate. In fact, it's a lot of boiler plate that can go wrong. I have a lot more faith in the exception system of most languages than I do a rats nest of if-else-if-else statements that 'Fresh-out-of-college' Fred wrote, and I have a lot better things to do with my time than code reviewing said rat's nest.
My reasoning would be if you are writing a low-level driver that really needs performance, then use error codes. But if you're using that code in a higher-level application and it can handle a bit of overhead, then wrap that code with an interface which checks those error codes and raises exceptions.
In all other cases, exceptions are probably the way to go.
My approach is that we can use both, i.e. Exceptions and Errors codes at the same time.
I'm used to define several types of Exceptions (ex: DataValidationException or ProcessInterruptExcepion) and inside each exception define a more detailed description of each problem.
A Simple Example in Java:
public class DataValidationException extends Exception {
private DataValidation error;
/**
*
*/
DataValidationException(DataValidation dataValidation) {
super();
this.error = dataValidation;
}
}
enum DataValidation{
TOO_SMALL(1,"The input is too small"),
TOO_LARGE(2,"The input is too large");
private DataValidation(int code, String input) {
this.input = input;
this.code = code;
}
private String input;
private int code;
}
In this way i use Exceptions to define category errors, and error codes to define more detailed info about the problem.
I may be sitting on the fence here, but...
It depends on the language.
Whichever model you choose, be consistent about how you use it.
In Python, use of exceptions is standard practice, and I'm quite happy to define my own exceptions. In C you don't have exceptions at all.
In C++ (in the STL at least), exceptions are typically only thrown for truly exceptional errors (I virtually never see them myself). I see no reason to do anything different in my own code. Yes it's easy to ignore return values, but C++ doesn't force you to catch exceptions either. I think you just have to get into the habit of doing it.
The code base I work on is mostly C++ and we use error codes almost everywhere, but there's one module that raises exceptions for any error, including very unexceptional ones, and all the code that uses that module is pretty horrible. But that might just be because we've mixed exceptions and error codes. The code that consistently uses error codes is much easier to work with. If our code consistently used exceptions, maybe it wouldn't be as bad. Mixing the two doesn't seem to work so well.
Since I work with C++, and have RAII to make them safe to use, I use exceptions almost exclusively. It pulls error handling out of the normal program flow and makes the intent more clear.
I do leave exceptions for exceptional circumstances though. If I'm expecting that a certain error is going to happen a lot I'll check that the operation will succeed before performing it, or call a version of the function that uses error codes instead (Like TryParse())
Method signatures should communicate to you what the method does. Something like
long errorCode = getErrorCode();
might be fine, but
long errorCode = fetchRecord();
is confusing.
Exceptions are for exceptional circumstances - ie, when they are not part of the normal flow of the code.
It's quite legitimate to mix Exceptions and error codes, where error codes represent the status of something, rather than an error in the running of the code per se (e.g. checking the return code from a child process).
But when an exceptional circumstance occurs I believe Exceptions are the most expressive model.
There are cases where you might prefer, or have, to use error codes in place of Exceptions, and these have been adequately covered already (other than other obvious constrains such as compiler support).
But going in the other direction, using Exceptions allows you to build even higher level abstractions to your error handling, that can make your code even more expressive and natural. I would highly recommend reading this excellent, yet underrated, article by C++ expert Andrei Alexandrescu on the subject of what he calls, "Enforcements": http://www.ddj.com/cpp/184403864. Although it's a C++ article the principles are generally applicable, and I have translated the enforcements concept to C# quite successfully.
First, I agree with Tom's answer that for high-level stuff use exceptions, and for low-level stuff use error codes, as long as it is not Service Oriented Architecture (SOA).
In SOA, where methods may be called across different machines, exceptions may not be passed over the wire, instead, we use success/failure responses with a structure like below (C#):
public class ServiceResponse
{
public bool IsSuccess => string.IsNullOrEmpty(this.ErrorMessage);
public string ErrorMessage { get; set; }
}
public class ServiceResponse<TResult> : ServiceResponse
{
public TResult Result { get; set; }
}
And use like this:
public async Task<ServiceResponse<string>> GetUserName(Guid userId)
{
var response = await this.GetUser(userId);
if (!response.IsSuccess) return new ServiceResponse<string>
{
ErrorMessage = $"Failed to get user."
};
return new ServiceResponse<string>
{
Result = user.Name
};
}
When these are used consistently in your service responses it creates a very nice pattern of handling success/failures in the application. This allows easier error handling in async calls within services as well as across services.
I would prefer Exceptions for all error cases, except when a failure is an expectable bug-free result of a function that returns a primitive datatype. E.g. finding the index of a substring within a larger string would usually return -1 if not found, instead of raising a NotFoundException.
Returning invalid pointers that might be dereferenced (e.g. causing NullPointerException in Java) is not acceptable.
Using multiple different numerical error codes (-1, -2) as return values for the same function is usually bad style, as clients might do a "== -1" check instead of "< 0".
One thing to keep in mind here is the evolution of APIs over time. A good API allows to change and extend failure behavior in several ways without breaking clients. E.g. if a client error handle checked for 4 error cases, and you add a fifth error value to your function, the client handler may not test this and break. If you raise Exceptions, this will usually make it easier for clients to migrate to a newer version of a library.
Another thing to consider is when working in a team, where to draw a clear line for alldevelopers to make such a decision. E.g. "Exceptions for high-level stuff, error codes for low-level stuff" is very subjective.
In any case, where more than one trivial type of error is possible, the source code should never use the numeric literal to return an error code or to handle it (return -7, if x == -7 ...), but always a named constant (return NO_SUCH_FOO, if x == NO_SUCH_FOO) .
If you work under big project, you can't use only exceptions or only error codes. In different cases you should use different approaches.
For example, you decide to use exceptions only. But once you decide to use async event processing. It is bad idea to use exceptions for error handling in this situations. But use error codes everywhere in application is tedious.
So my opinion that it is normal to use both exceptions and error codes simultaneous.
For most applications, exceptions are better. The exception is when the software has to communicate with other devices. The domain I work in is industrial controls. Here errors codes are preferred and expected. So my answer is that it does depend on the situation.
I think it also depends on whether you really need information like stack trace from the result. If yes, you definitely go for Exception which provide object full with lots of information about problem. However, if you are just interested in result and don't care why that result then go for error code.
e.g. When you are processing file and face IOException, client might interested in knowing from where this was triggered, in opening file or parsing file etc. So better you return IOException or its specific subclass. However, scenario like you have login method and you want to know it was successful or not, there either you just return boolean or to show correct message, return error code. Here Client is not interested in knowing which part of logic caused that error code. He just know if its Credential invalid or account lock etc.
Another usecase I can think of is when data travels on network. Your remote method can return just error code instead of Exception to minimize data transfer.
My general rule is:
Only one error could appear in a function: use error code (as parameter of the function)
More than one specific error could appear: throw exception
Error codes also don't work when your method returns anything other than a numeric value...
My question is what do most developers prefer for error handling, Exceptions or Error Return Codes. Please be language(or language family) specific and why you prefer one over the other.
I'm asking this out of curiosity. Personally I prefer Error Return Codes since they are less explosive and don't force user code to pay the exception performance penalty if they don't want to.
update: thanks for all the answers! I must say that although I dislike the unpredictability of code flow with exceptions. The answer about return code (and their elder brother handles) do add lots of Noise to the code.
For some languages (i.e. C++) Resources leak should not be a reason
C++ is based on RAII.
If you have code that could fail, return or throw (that is, most normal code), then you should have your pointer wrapped inside a smart pointer (assuming you have a very good reason to not have your object created on stack).
Return codes are more verbose
They are verbose, and tend to develop into something like:
if(doSomething())
{
if(doSomethingElse())
{
if(doSomethingElseAgain())
{
// etc.
}
else
{
// react to failure of doSomethingElseAgain
}
}
else
{
// react to failure of doSomethingElse
}
}
else
{
// react to failure of doSomething
}
In the end, you code is a collection of idented instructions (I saw this kind of code in production code).
This code could well be translated into:
try
{
doSomething() ;
doSomethingElse() ;
doSomethingElseAgain() ;
}
catch(const SomethingException & e)
{
// react to failure of doSomething
}
catch(const SomethingElseException & e)
{
// react to failure of doSomethingElse
}
catch(const SomethingElseAgainException & e)
{
// react to failure of doSomethingElseAgain
}
Which cleanly separate code and error processing, which can be a good thing.
Return codes are more brittle
If not some obscure warning from one compiler (see "phjr" 's comment), they can easily be ignored.
With the above examples, assume than someone forgets to handle its possible error (this happens...). The error is ignored when "returned", and will possibly explode later (i.e. a NULL pointer). The same problem won't happen with exception.
The error won't be ignored. Sometimes, you want it to not explode, though... So you must chose carefully.
Return Codes must sometimes be translated
Let's say we have the following functions:
doSomething, which can return an int called NOT_FOUND_ERROR
doSomethingElse, which can return a bool "false" (for failed)
doSomethingElseAgain, which can return an Error object (with both the __LINE__, __FILE__ and half the stack variables.
doTryToDoSomethingWithAllThisMess which, well... Use the above functions, and return an error code of type...
What is the type of the return of doTryToDoSomethingWithAllThisMess if one of its called functions fail ?
Return Codes are not a universal solution
Operators cannot return an error code. C++ constructors can't, too.
Return Codes means you can't chain expressions
The corollary of the above point. What if I want to write:
CMyType o = add(a, multiply(b, c)) ;
I can't, because the return value is already used (and sometimes, it can't be changed). So the return value becomes the first parameter, sent as a reference... Or not.
Exception are typed
You can send different classes for each kind of exception. Ressources exceptions (i.e. out of memory) should be light, but anything else could be as heavy as necessary (I like the Java Exception giving me the whole stack).
Each catch can then be specialized.
Don't ever use catch(...) without re-throwing
Usually, you should not hide an error. If you do not re-throw, at the very least, log the error in a file, open a messagebox, whatever...
Exception are... NUKE
The problem with exception is that overusing them will produce code full of try/catches. But the problem is elsewhere: Who try/catch his/her code using STL container? Still, those containers can send an exception.
Of course, in C++, don't ever let an exception exit a destructor.
Exception are... synchronous
Be sure to catch them before they bring out your thread on its knees, or propagate inside your Windows message loop.
The solution could be mixing them?
So I guess the solution is to throw when something should not happen. And when something can happen, then use a return code or a parameter to enable to user to react to it.
So, the only question is "what is something that should not happen?"
It depends on the contract of your function. If the function accepts a pointer, but specifies the pointer must be non-NULL, then it is ok to throw an exception when the user sends a NULL pointer (the question being, in C++, when didn't the function author use references instead of pointers, but...)
Another solution would be to show the error
Sometimes, your problem is that you don't want errors. Using exceptions or error return codes are cool, but... You want to know about it.
In my job, we use a kind of "Assert". It will, depending on the values of a configuration file, no matter the debug/release compile options:
log the error
open a messagebox with a "Hey, you have a problem"
open a messagebox with a "Hey, you have a problem, do you want to debug"
In both development and testing, this enable the user to pinpoint the problem exactly when it is detected, and not after (when some code cares about the return value, or inside a catch).
It is easy to add to legacy code. For example:
void doSomething(CMyObject * p, int iRandomData)
{
// etc.
}
leads a kind of code similar to:
void doSomething(CMyObject * p, int iRandomData)
{
if(iRandomData < 32)
{
MY_RAISE_ERROR("Hey, iRandomData " << iRandomData << " is lesser than 32. Aborting processing") ;
return ;
}
if(p == NULL)
{
MY_RAISE_ERROR("Hey, p is NULL !\niRandomData is equal to " << iRandomData << ". Will throw.") ;
throw std::some_exception() ;
}
if(! p.is Ok())
{
MY_RAISE_ERROR("Hey, p is NOT Ok!\np is equal to " << p->toString() << ". Will try to continue anyway") ;
}
// etc.
}
(I have similar macros that are active only on debug).
Note that on production, the configuration file does not exist, so the client never sees the result of this macro... But it is easy to activate it when needed.
Conclusion
When you code using return codes, you're preparing yourself for failure, and hope your fortress of tests is secure enough.
When you code using exception, you know that your code can fail, and usually put counterfire catch at chosen strategic position in your code. But usually, your code is more about "what it must do" then "what I fear will happen".
But when you code at all, you must use the best tool at your disposal, and sometimes, it is "Never hide an error, and show it as soon as possible". The macro I spoke above follow this philosophy.
I use both actually.
I use return codes if it's a known, possible error. If it's a scenario that I know can, and will happen, then there's a code that gets sent back.
Exceptions are used solely for things that I'm NOT expecting.
According to Chapter 7 titled "Exceptions" in Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, numerous rationales are given for why using exceptions over return values is necessary for OO frameworks such as C#.
Perhaps this is the most compelling reason (page 179):
"Exceptions integrate well with object-oriented languages. Object-oriented languages tend to impose constraints on member signatures that are not imposed by functions in non-OO languages. For example, in the case of constructors, operator overloads, and properties, the developer has no choice in the return value. For this reason, it is not possible to standardize on return-value-based error reporting for object-oriented frameworks. An error reporting method, such as exceptions, which is out of band of the method signature is the only option."
My preference (in C++ and Python) is to use exceptions. The language-provided facilities make it a well-defined process to both raise, catch and (if necessary) re-throw exceptions, making the model easy to see and use. Conceptually, it's cleaner than return codes, in that specific exceptions can be defined by their names, and have additional information accompanying them. With a return code, you're limited to just the error value (unless you want to define an ReturnStatus object or something).
Unless the code you're writing is time-critical, the overhead associated with unwinding the stack is not significant enough to worry about.
Exceptions should only be returned where something happens that you were not expecting.
The other point of exceptions, historically, is that return codes are inherently proprietary, sometimes a 0 could be returned from a C function to indicate success, sometimes -1, or either of them for a fail with 1 for a success. Even when they are enumerated, enumerations can be ambiguous.
Exceptions can also provide a lot more information, and specifically spell out well 'Something Went Wrong, here's what, a stack trace and some supporting information for the context'
That being said, a well enumerated return code can be useful for a known set of outcomes, a simple 'heres n outcomes of the function, and it just ran this way'
Always use exceptions by default, BUT consider providing an additional tester-doer option (TryX)!
For me the answer is really clear. When the context dictates a Try or Tester-Doer pattern (ie cpu intensive or public api), I will ADDITIONALLY provide those methods to the exception throwing version. I think blanket rules of avoiding exceptions are misguided, unsupported, and likely cause far more expense in terms of bugs, than any performance issues they claim to prevent.
No, Microsoft does NOT say to not use exceptions (common misinterpretation).
It says if you're designing an API provide ways to help a user of that API to avoid THROWING exceptions if they need too (Try and Tester-Doer patterns)
❌ DO NOT use exceptions for the normal flow of control, if possible.
Except for system failures and operations with potential race
conditions, framework designers should design APIs so users can write
code that does not throw exceptions. For example, you can provide a
way to check preconditions before calling a member so users can write
code that does not throw exceptions.
What is inferred here is that the non-tester-doer/non-try implementation SHOULD throw an exception upon failure and then the user CAN change that to one of your tester-doer or try methods for performance. Pit of success is maintained for safety and the user OPTS INTO the more dangerous but more performant method.
Microsoft DOES say to NOT use return codes TWICE, here:
❌ DO NOT return error codes.
Exceptions are the primary means of reporting errors in frameworks.
✔️ DO report execution failures by throwing exceptions.
and here:
❌ DO NOT use error codes because of concerns that exceptions might
affect performance negatively.
To improve performance, it is possible to use either the Tester-Doer
Pattern or the Try-Parse Pattern, described in the next two sections.
If you're not using exceptions you're probably breaking this other rule of returning return codes or booleans from a non-tester/non-try implementation.
Again, TryParse does not replace Parse. It is provided in addition to Parse
MAIN REASON: Return codes fail the "Pit of Success" test for me almost every time.
It is far too easy to forget to check a return code and then have a red-herring error later on.
var success = Save()? How much performance is worth someone forgetting an if check here?
var success = TrySave()? Better, but are we going to abuse everything with the TryX pattern? Did you still provide a Save method?
Return codes don't have any of the great debugging information on them like call stack, inner exceptions.
Return codes do not propagate which, along with the point above, tends to drive excessive and interwoven diagnostic logging instead of logging in one centralized place (application and thread level exception handlers).
Return codes tend to drive messy code in the form of nested 'if' blocks
Developer time spent debugging an unknown issue that would otherwise have been an obvious exception (pit of success) IS expensive.
If the team behind C# didn't intend for exceptions to govern control flow, execeptions wouldn't be typed, there would be no "when" filter on catch statements, and there would be no need for the parameter-less 'throw' statement.
Regarding Performance:
Exceptions may be computationally expensive RELATIVE to not throwing at all, but they're called EXCEPTIONS for a reason. Speed comparisons always manage to assume a 100% exception rate which should never be the case. Even if an exception is 100x slower, how much does that really matter if it only happens 1% of the time?
Context is everything. For example, A Tester-Doer or Try option to avoid a unique key violation is likely to waste more time and resources on average (checking for existance when a collision is rare) than just assuming a successful entry and catching that rare violation.
Unless we're talking floating point arithmetic for graphics applications or something similar, CPU cycles are cheap compared to developer time.
Cost from a time perspective carries the same argument. Relative to database queries or web service calls or file loads, normal application time will dwarf exception time. Exceptions were nearly sub-MICROsecond in 2006
I dare anybody that works in .net, to set your debugger to break on all exceptions and disable just my code and see how many exceptions are already happening that you don't even know about.
Jon Skeet says "[Exceptions are] not slow enough to make it worth avoiding them in normal use". The linked response also contains two articles from Jon on the subject. His generalized theme is that exceptions are fine and if you're experiencing them as a performance problem, there's likely a larger design issue.
In Java, I use (in the following order):
Design-by-contract (ensuring preconditions are met before trying anything that might fail). This catches most things and I return an error code for this.
Returning error codes whilst processing work (and performing rollback if needed).
Exceptions, but these are used only for unexpected things.
I dislike return codes because they cause the following pattern to mushroom throughout your code
CRetType obReturn = CODE_SUCCESS;
obReturn = CallMyFunctionWhichReturnsCodes();
if (obReturn == CODE_BLOW_UP)
{
// bail out
goto FunctionExit;
}
Soon a method call consisting of 4 function calls bloats up with 12 lines of error handling.. Some of which will never happen. If and switch cases abound.
Exceptions are cleaner if you use them well... to signal exceptional events .. after which the execution path cannot continue. They are often more descriptive and informational than error codes.
If you have multiple states after a method call that should be handled differently (and are not exceptional cases), use error codes or out params. Although Personaly I've found this to be rare..
I've hunted a bit about the 'performance penalty' counterargument.. more in the C++ / COM world but in the newer languages, I think the difference isn't that much. In any case, when something blows up, performance concerns are relegated to the backburner :)
I wrote a blog post about this a while ago.
The performance overhead of throwing an exception should not play any role in your decision. If you're doing it right, after all, an exception is exceptional.
A great piece of advice I got from The Pragmatic Programmer was something along the lines of "your program should be able to perform all its main functionality without using exceptions at all".
I have a simple set of rules:
1) Use return codes for things you expect your immediate caller to react to.
2) Use exceptions for errors that are broader in scope, and may reasonable be expected to be handled by something many levels above the caller so that awareness of the error does not have to percolate up through many layers, making code more complex.
In Java I only ever used unchecked exceptions, checked exceptions end up just being another form of return code and in my experience the duality of what might be "returned" by a method call was generally more of a hinderance than a help.
I use Exceptions in python in both Exceptional, and non-Exceptional circumstances.
It is often nice to be able to use an Exception to indicate the "request could not be performed", as opposed to returning an Error value. It means that you /always/ know that the return value is the right type, instead of arbitarily None or NotFoundSingleton or something. Here is a good example of where I prefer to use an exception handler instead of a conditional on the return value.
try:
dataobj = datastore.fetch(obj_id)
except LookupError:
# could not find object, create it.
dataobj = datastore.create(....)
The side effect is that when a datastore.fetch(obj_id) is run, you never have to check if its return value is None, you get that error immediately for free. This is counter to the argument, "your program should be able to perform all its main functionality without using exceptions at all".
Here is another example of where exceptions are 'exceptionally' useful, in order to write code for dealing with the filesystem that isn't subject to race conditions.
# wrong way:
if os.path.exists(directory_to_remove):
# race condition is here.
os.path.rmdir(directory_to_remove)
# right way:
try:
os.path.rmdir(directory_to_remove)
except OSError:
# directory didn't exist, good.
pass
One system call instead of two, no race condition. This is a poor example because obviously this will fail with an OSError in more circumstances than the directory doesn't exist, but it's a 'good enough' solution for many tightly controlled situations.
I believe the return codes adds to code noise. For example, I always hated the look of COM/ATL code due to return codes. There had to be an HRESULT check for every line of code. I consider the error return code is one of the bad decisions made by architects of COM. It makes it difficult to do logical grouping of the code, thus code review becomes difficult.
I am not sure about the performance comparison when there is an explicit check for the return code every line.
Exceptions are not for error handling, IMO. Exceptions are just that; exceptional events that you did not expect. Use with caution I say.
Error codes can be OK, but returning 404 or 200 from a method is bad, IMO. Use enums (.Net) instead, that makes the code more readable and easier to use for other developers. Also you don't have to maintain a table over numbers and descriptions.
Also; the try-catch-finally pattern is an anti-pattern in my book. Try-finally can be good, try-catch can also be good but try-catch-finally is never good. try-finally can often times be replaced by a "using" statement (IDispose pattern), which is better IMO. And Try-catch where you actually catch an exception you're able to handle is good, or if you do this:
try{
db.UpdateAll(somevalue);
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
So as long as you let the exception continue to bubble it's OK. Another example is this:
try{
dbHasBeenUpdated = db.UpdateAll(somevalue); // true/false
}
catch (ConnectionException ex) {
logger.Exception(ex, "Connection failed");
dbHasBeenUpdated = false;
}
Here I actually handle the exception; what I do outside of the try-catch when the update method fails is another story, but I think my point has been made. :)
Why is then try-catch-finally an anti-pattern? Here's why:
try{
db.UpdateAll(somevalue);
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
finally {
db.Close();
}
What happens if the db object has already been closed? A new exception is thrown and it has to be handled! This is better:
try{
using(IDatabase db = DatabaseFactory.CreateDatabase()) {
db.UpdateAll(somevalue);
}
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
Or, if the db object does not implement IDisposable do this:
try{
try {
IDatabase db = DatabaseFactory.CreateDatabase();
db.UpdateAll(somevalue);
}
finally{
db.Close();
}
}
catch (DatabaseAlreadyClosedException dbClosedEx) {
logger.Exception(dbClosedEx, "Database connection was closed already.");
}
catch (Exception ex) {
logger.Exception(ex, "UpdateAll method failed");
throw;
}
That's my 2 cents anyway! :)
I generally prefer return codes because they let the caller decide whether the failure is exceptional.
This approach is typical in the Elixir language.
# I care whether this succeeds. If it doesn't return :ok, raise an exception.
:ok = File.write(path, content)
# I don't care whether this succeeds. Don't check the return value.
File.write(path, content)
# This had better not succeed - the path should be read-only to me.
# If I get anything other than this error, raise an exception.
{:error, :erofs} = File.write(path, content)
# I want this to succeed but I can handle its failure
case File.write(path, content) do
:ok => handle_success()
error => handle_error(error)
end
People mentioned that return codes can cause you to have a lot of nested if statements, but that can be handled with better syntax. In Elixir, the with statement lets us easily separate a series of happy-path return value from any failures.
with {:ok, content} <- get_content(),
:ok <- File.write(path, content) do
IO.puts "everything worked, happy path code goes here"
else
# Here we can use a single catch-all failure clause
# or match every kind of failure individually
# or match subsets of them however we like
_some_error => IO.puts "one of those steps failed"
_other_error => IO.puts "one of those steps failed"
end
Elixir still has functions that raise exceptions. Going back to my first example, I could do either of these to raise an exception if the file can't be written.
# Raises a generic MatchError because the return value isn't :ok
:ok = File.write(path, content)
# Raises a File.Error with a descriptive error message - eg, saying
# that the file is read-only
File.write!(path, content)
If I, as the caller, know that I want to raise an error if the write fails, I can choose to call File.write! instead of File.write.
Or I can choose to call File.write and handle each of the possible reasons for failure differently.
Of course it's always possible to rescue an exception if we want to. But compared to handling an informative return value, it seems awkward to me. If I know that a function call can fail or even should fail, its failure isn't an exceptional case.
With any decent compiler or runtime environment exceptions do not incur a significant penalty. It's more or less like a GOTO statement that jumps to the exception handler. Also, having exceptions caught by a runtime environment (like the JVM) helps isolating and fixing a bug a lot easier. I'll take a NullPointerException in Java over a segfault in C any day.
I prefer to use exceptions for error handling and return values (or parameters) as the normal result of a function. This gives an easy and consistent error-handling scheme and if done correctly it makes for much cleaner looking code.
One of the big differences is that exceptions force you to handle an error, whereas error return codes can go unchecked.
Error return codes, if used heavily, can also cause very ugly code with lots of if tests similar to this form:
if(function(call) != ERROR_CODE) {
do_right_thing();
}
else {
handle_error();
}
Personally I prefer to use exceptions for errors that SHOULD or MUST be acted upon by the calling code, and only use error codes for "expected failings" where returning something is actually valid and possible.
There is many reason to prefer Exceptions over return code:
Usually, for readibility, people try to minimize the number of return statement in a method. Doing so, exceptions prevent to do some extra work while in a incoorect state, and thus prevent to potentially damage more data.
Exception are generally more verbose arn more easilly extensible than return value. Assume that a method return natural number and that you use negative numbers as return code when an error occurs, if the scope of you method change and now return integers, you'll have to modify all the method calls instead of just tweaking a little bit the exception.
Exceptions allows more easilly to separate error handling of normal behaviour. They allows to ensure that some operations performs somehow as an atomic operation.
I only use exceptions, no return codes. I'm talking about Java here.
The general rule I follow is if I have a method called doFoo() then it follows that if it doesn't "do foo", as it were, then something exceptional has happened and an Exception should be thrown.
One thing I fear about exceptions is that throwing an exception will screw up code flow. For example if you do
void foo()
{
MyPointer* p = NULL;
try{
p = new PointedStuff();
//I'm a module user and I'm doing stuff that might throw or not
}
catch(...)
{
//should I delete the pointer?
}
}
Or even worse what if I deleted something I shouldn't have, but got thrown to catch before I did the rest of the cleanup. Throwing put a lot of weight on the poor user IMHO.
My general rule in the exception vs. return code argument:
Use errorcodes when you need localization/internationalization -- in .NET, you could use these errorcodes to reference a resource file which will then display the error in the appropriate language. Otherwise, use exceptions
Use exceptions only for errors that are really exceptional. If it's something that happens fairly often, either use a boolean or an enum errorcode.
I don't find return codes to be less ugly than exceptions. With the exception, you have the try{} catch() {} finally {} where as with return codes you have if(){}. I used to fear exceptions for the reasons given in the post; you don't know if the pointer needs to be cleared, what have you. But I think you have the same problems when it comes to the return codes. You don't know the state of the parameters unless you know some details about the function/method in question.
Regardless, you have to handle the error if possible. You can just as easily let an exception propagate to the top level as ignore a return code and let the program segfault.
I do like the idea of returning a value (enumeration?) for results and an exception for an exceptional case.
For a language like Java, I would go with Exception because the compiler gives compile time error if exceptions are not handled.This forces the calling function to handle/throw the exceptions.
For Python, I am more conflicted. There is no compiler so it's possible that caller does not handle the exception thrown by the function leading to runtime exceptions. If you use return codes you might have unexpected behavior if not handled properly and if you use exceptions you might get runtime exceptions.
There are some important aspects that remain unmentioned in this - very interesting - discussion so far.
First, it is important to note that exceptions don't apply to distributed computing, but error codes still do. Imagine communicating services distributed over multiple servers. Some communication might even be asynchronous. And the services might even use different technology stacks. Cleary, an error-handling concept is crucial here. And clearly, exceptions can't be used in this most general case, since errors have to be serialized things sent "through the cable", perhaps even in a language-neutral way. From that angle, error codes (really, error messages) are more universal than exceptions. One needs good error-message Kung Fu once one assumes a system-architect view and things need to scale.
The second point is a very different, it is about if or how a language represents discriminated unions. The question was strictly speaking about "error codes". And so were some the answers, mentioning that error codes cannot transport information as nicely as exceptions. This is true if an error code is a number. But for a fairer contrasting with exceptions, one should probably consider error values of discriminated union type. So, the return value of the callee would be of discriminated union type, and it would either be the desired happy-path value or the payload the exception would otherwise have. How often this approach is elegant enough to be preferable depends on the programming language. For example, F# has super elegant discriminated unions and the according pattern matching. In such a language it would be more seductive to avoid exceptions than in, say, C++.
The third and final point is about functional programming and pure functions. Exceptions are (in a practical way and in a theoretical-computer-science way) "side effects". In other words, functions or methods that deal with exceptions are not pure. (One practical consequence is that with exceptions one must pay attention to evaluation order.) By contrast, error values are pure, because the are just ordinary return values, with no side effects involved. Therefore, functional programmers may more likely frown upon exceptions than object-oriented programmers. (In particular if the language also has an elegant representation of the aforementioned discriminated unions.)
I prefer exceptions over return codes.
Consider a scenario when I call a function foo and forget to handle potential errors (exceptions).
If errors in foo are passed via return codes (error codes),
at compile time, I won't be alerted
if I run the code
if the error doesn't happen, I don't notice my mistake
if the error happens but doesn't affect the code after calling foo, I don't notice my mistake
if the error happens and affects the code after calling foo, I notice my mistake, but it may be hard to locate the problem
If errors in foo are passed via exceptions that are thrown,
at compile time, I won't be alerted
if I run the code
if the error doesn't happen, I don't notice my mistake
if the error happens, I'm assured to notice my mistake
From the comparison above, my conclusion is that exceptions are better than error codes.
However, exceptions are not perfect. There are at least two critical problems:
As discussed above, if I forget to handle a potential exception, I won't be alerted until I run the code and the exception is actually thrown.
It's hard to determine all the exceptions foo may throw, especially when foo calls other functions (which may also throw exceptions).
A feature in Java, “checked exceptions”, solves both problems.
In Java, when defining a function foo, I'm required to explicitly specify what exceptions it may throw using the throws keyword. Example:
private static void foo() throws FileNotFoundException {
File file = new File("not_existing_file.txt");
FileInputStream stream = new FileInputStream(file);
}
If I call foo and forget to handle the potential FileNotFoundException, the compiler produces an error. I get alerted at compile time (problem 1 solved). And all possible exceptions are listed explicitly (problem 2 solved).
I have exceptions created for every condition that my application does not expect. UserNameNotValidException, PasswordNotCorrectException etc.
However I was told I should not create exceptions for those conditions. In my UML those ARE exceptions to the main flow, so why should it not be an exception?
Any guidance or best practices for creating exceptions?
My personal guideline is: an exception is thrown when a fundamental assumption of the current code block is found to be false.
Example 1: say I have a function which is supposed to examine an arbitrary class and return true if that class inherits from List<>. This function asks the question, "Is this object a descendant of List?" This function should never throw an exception, because there are no gray areas in its operation - every single class either does or does not inherit from List<>, so the answer is always "yes" or "no".
Example 2: say I have another function which examines a List<> and returns true if its length is more than 50, and false if the length is less. This function asks the question, "Does this list have more than 50 items?" But this question makes an assumption - it assumes that the object it is given is a list. If I hand it a NULL, then that assumption is false. In that case, if the function returns either true or false, then it is breaking its own rules. The function cannot return anything and claim that it answered the question correctly. So it doesn't return - it throws an exception.
This is comparable to the "loaded question" logical fallacy. Every function asks a question. If the input it is given makes that question a fallacy, then throw an exception. This line is harder to draw with functions that return void, but the bottom line is: if the function's assumptions about its inputs are violated, it should throw an exception instead of returning normally.
The other side of this equation is: if you find your functions throwing exceptions frequently, then you probably need to refine their assumptions.
Because they're things that will happen normally. Exceptions are not control flow mechanisms. Users often get passwords wrong, it's not an exceptional case. Exceptions should be a truly rare thing, UserHasDiedAtKeyboard type situations.
My little guidelines are heavily influenced by the great book "Code complete":
Use exceptions to notify about things that should not be ignored.
Don't use exceptions if the error can be handled locally
Make sure the exceptions are at the same level of abstraction as the rest of your routine.
Exceptions should be reserved for what's truly exceptional.
It is NOT an exception if the username is not valid or the password is not correct. Those are things you should expect in the normal flow of operation. Exceptions are things that are not part of the normal program operation and are rather rare.
I do not like using exceptions because you can not tell if a method throws an exception just by looking at the call. Thats why exceptions should only be used if you can't handle the situation in a decent manner (think "out of memory" or "computer is on fire").
One rule of thumb is to use exceptions in the case of something you couldn't normally predict. Examples are database connectivity, missing file on disk, etc. For scenarios that you can predict, ie users attempting to log in with a bad password you should be using functions that return booleans and know how to handle the situation gracefully. You don't want to abruptly end execution by throwing an exception just because someone mistyped their password.
Others propose that exceptions should not be used because the bad login is to be expected in a normal flow if the user mistypes. I disagree and I don't get the reasoning. Compare it with opening a file.. if the file doesn't exist or is not available for some reason then an exception will be thrown by the framework. Using the logic above this was a mistake by Microsoft. They should have returned an error code. Same for parsing, webrequests, etc., etc..
I don't consider a bad login part of a normal flow, it's exceptional. Normally the user types the correct password, and the file does exist. The exceptional cases are exceptional and it's perfectly fine to use exceptions for those. Complicating your code by propagating return values through n levels up the stack is a waste of energy and will result in messy code. Do the simplest thing that could possibly work. Don't prematurely optimize by using error codes, exceptional stuff by definition rarely happens, and exceptions don't cost anything unless you throw them.
I think you should only throw an exception when there's nothing you can do to get out of your current state. For example if you are allocating memory and there isn't any to allocate. In the cases you mention you can clearly recover from those states and can return an error code back to your caller accordingly.
You will see plenty of advice, including in answers to this question, that you should throw exceptions only in "exceptional" circumstances. That seems superficially reasonable, but is flawed advice, because it replaces one question ("when should I throw an exception") with another subjective question ("what is exceptional"). Instead, follow the advice of Herb Sutter (for C++, available in the Dr Dobbs article When and How to Use Exceptions, and also in his book with Andrei Alexandrescu, C++ Coding Standards): throw an exception if, and only if
a precondition is not met (which typically makes one of the following
impossible) or
the alternative would fail to meet a post-condition or
the alternative would fail to maintain an invariant.
Why is this better? Doesn't it replace the question with several questions about preconditions, postconditions and invariants? This is better for several connected reasons.
Preconditions, postconditions and invariants are design characteristics of our program (its internal API), whereas the decision to throw is an implementation detail. It forces us to bear in mind that we must consider the design and its implementation separately, and our job while implementing a method is to produce something that satisfies the design constraints.
It forces us to think in terms of preconditions, postconditions and invariants, which are the only assumptions that callers of our method should make, and are expressed precisely, enabling loose coupling between the components of our program.
That loose coupling then allows us to refactor the implementation, if necessary.
The post-conditions and invariants are testable; it results in code that can be easily unit tested, because the post-conditions are predicates our unit-test code can check (assert).
Thinking in terms of post-conditions naturally produces a design that has success as a post-condition, which is the natural style for using exceptions. The normal ("happy") execution path of your program is laid out linearly, with all the error handling code moved to the catch clauses.
Exceptions are a somewhat costly effect, if for example you have a user that provides an invalid password, it is typically a better idea to pass back a failure flag, or some other indicator that it is invalid.
This is due to the way that exceptions are handled, true bad input, and unique critical stop items should be exceptions, but not failed login info.
I would say there are no hard and fast rules on when to use exceptions. However there are good reasons for using or not using them:
Reasons to use exceptions:
The code flow for the common case is clearer
Can return complex error information as an object (although this can also be achieved using error "out" parameter passed by reference)
Languages generally provide some facility for managing tidy cleanup in the event of the exception (try/finally in Java, using in C#, RAII in C++)
In the event no exception is thrown, execution can sometimes be faster than checking return codes
In Java, checked exceptions must be declared or caught (although this can be a reason against)
Reasons not to use exceptions:
Sometimes it's overkill if the error handling is simple
If exceptions are not documented or declared, they may be uncaught by calling code, which may be worse than if the the calling code just ignored a return code (application exit vs silent failure - which is worse may depend on the scenario)
In C++, code that uses exceptions must be exception safe (even if you don't throw or catch them, but call a throwing function indirectly)
In C++, it is hard to tell when a function might throw, therefore you must be paranoid about exception safety if you use them
Throwing and catching exceptions is generally significantly more expensive compared to checking a return flag
In general, I would be more inclined to use exceptions in Java than in C++ or C#, because I am of the opinion that an exception, declared or not, is fundamentally part of the formal interface of a function, since changing your exception guarantee may break calling code. The biggest advantage of using them in Java IMO, is that you know that your caller MUST handle the exception, and this improves the chance of correct behaviour.
Because of this, in any language, I would always derive all exceptions in a layer of code or API from a common class, so that calling code can always guarantee to catch all exceptions. Also I would consider it bad to throw exception classes that are implementation-specific, when writing an API or library (i.e. wrap exceptions from lower layers so that the exception that your caller receives is understandable in the context of your interface).
Note that Java makes the distinction between general and Runtime exceptions in that the latter need not be declared. I would only use Runtime exception classes when you know that the error is a result of a bug in the program.
If it's code running inside a loop that will likely cause an exception over and over again, then throwing exceptions is not a good thing, because they are pretty slow for large N. But there is nothing wrong with throwing custom exceptions if the performance is not an issue. Just make sure that you have a base exception that they all inherite, called BaseException or something like that. BaseException inherits System.Exception, but all of your exceptions inherit BaseException. You can even have a tree of Exception types to group similar types, but this may or may not be overkill.
So, the short answer is that if it doesn't cause a significant performance penalty (which it should not unless you are throwing a lot of exceptions), then go ahead.
Exception classes are like "normal" classes. You create a new class when it "is" a different type of object, with different fields and different operations.
As a rule of thumb, you should try balance between the number of exceptions and the granularity of the exceptions. If your method throws more than 4-5 different exceptions, you can probably merge some of them into more "general" exceptions, (e.g. in your case "AuthenticationFailedException"), and using the exception message to detail what went wrong. Unless your code handles each of them differently, you needn't creates many exception classes. And if it does, may you should just return an enum with the error that occured. It's a bit cleaner this way.
the rule of thumb for throwing exceptions is pretty simple. you do so when your code has entered into an UNRECOVERABLE INVALID state. if data is compromised or you cannot wind back the processing that occurred up to the point then you must terminate it. indeed what else can you do? your processing logic will eventually fail elsewhere. if you can recover somehow then do that and do not throw exception.
in your particular case if you were forced to do something silly like accept money withdrawal and only then check user/pasword you should terminate the process by throwing an exception to notify that something bad has happened and prevent further damage.
I agree with japollock way up there--throw an acception when you are uncertain about the outcome of an operation. Calls to APIs, accessing filesystems, database calls, etc. Anytime you are moving past the "boundaries" of your programming languages.
I'd like to add, feel free to throw a standard exception. Unless you are going to do something "different" (ignore, email, log, show that twitter whale picture thingy, etc), then don't bother with custom exceptions.
I'd say that generally every fundamentalism leads to hell.
You certainly wouldn't want to end up with exception driven flow, but avoiding exceptions altogether is also a bad idea. You have to find a balance between both approaches. What I would not do is to create an exception type for every exceptional situation. That is not productive.
What I generally prefer is to create two basic types of exceptions which are used throughout the system: LogicalException and TechnicalException. These can be further distinguished by subtypes if needed, but it is not generally not necessary.
The technical exception denotes the really unexpected exception like database server being down, the connection to the web service threw the IOException and so on.
On the other hand the logical exceptions are used to propagate the less severe erroneous situation to the upper layers (generally some validation result).
Please note that even the logical exception is not intended to be used on regular basis to control the program flow, but rather to highlight the situation when the flow should really end. When used in Java, both exception types are RuntimeException subclasses and error handling is highly aspect oriented.
So in the login example it might be wise to create something like AuthenticationException and distinguish the concrete situations by enum values like UsernameNotExisting, PasswordMismatch etc. Then you won't end up in having a huge exception hierarchy and can keep the catch blocks on maintainable level. You can also easily employ some generic exception handling mechanism since you have the exceptions categorized and know pretty well what to propagate up to the user and how.
Our typical usage is to throw the LogicalException during the Web Service call when the user's input was invalid. The Exception gets marshalled to the SOAPFault detail and then gets unmarshalled to the exception again on the client which is resulting in showing the validation error on one certain web page input field since the exception has proper mapping to that field.
This is certainly not the only situation: you don't need to hit web service to throw up the exception. You are free to do so in any exceptional situation (like in the case you need to fail-fast) - it is all at your discretion.
In general you want to throw an exception for anything that can happen in your application that is "Exceptional"
In your example, both of those exceptions look like you are calling them via a password / username validation. In that case it can be argued that it isn't really exceptional that someone would mistype a username / password.
They are "exceptions" to the main flow of your UML but are more "branches" in the processing.
If you attempted to access your passwd file or database and couldn't, that would be an exceptional case and would warrant throwing an exception.
Firstly, if the users of your API aren't interested in specific, fine-grained failures, then having specific exceptions for them isn't of any value.
Since it's often not possible to know what may be useful to your users, a better approach is to have the specific exceptions, but ensure they inherit from a common class (e.g., std::exception or its derivatives in C++). That allows your client to catch specific exceptions if they choose, or the more general exception if they don't care.
Exceptions are intended for events that are abnormal behaviors, errors, failures, and such. Functional behavior, user error, etc., should be handled by program logic instead. Since a bad account or password is an expected part of the logic flow in a login routine, it should be able to handle those situations without exceptions.
The simple answer is, whenever an operation is impossible (because of either application OR because it would violate business logic). If a method is invoked and it impossible to do what the method was written to do, throw an Exception. A good example is that constructors always throw ArgumentExceptions if an instance cannot be created using the supplied parameters. Another example is InvalidOperationException, which is thrown when an operation cannot be performed because of the state of another member or members of the class.
In your case, if a method like Login(username, password) is invoked, if the username is not valid, it is indeed correct to throw a UserNameNotValidException, or PasswordNotCorrectException if password is incorrect. The user cannot be logged in using the supplied parameter(s) (i.e. it's impossible because it would violate authentication), so throw an Exception. Although I might have your two Exceptions inherit from ArgumentException.
Having said that, if you wish NOT to throw an Exception because a login failure may be very common, one strategy is to instead create a method that returns types that represent different failures. Here's an example:
{ // class
...
public LoginResult Login(string user, string password)
{
if (IsInvalidUser(user))
{
return new UserInvalidLoginResult(user);
}
else if (IsInvalidPassword(user, password))
{
return new PasswordInvalidLoginResult(user, password);
}
else
{
return new SuccessfulLoginResult();
}
}
...
}
public abstract class LoginResult
{
public readonly string Message;
protected LoginResult(string message)
{
this.Message = message;
}
}
public class SuccessfulLoginResult : LoginResult
{
public SucccessfulLogin(string user)
: base(string.Format("Login for user '{0}' was successful.", user))
{ }
}
public class UserInvalidLoginResult : LoginResult
{
public UserInvalidLoginResult(string user)
: base(string.Format("The username '{0}' is invalid.", user))
{ }
}
public class PasswordInvalidLoginResult : LoginResult
{
public PasswordInvalidLoginResult(string password, string user)
: base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
{ }
}
Most developers are taught to avoid Exceptions because of the overhead caused by throwing them. It's great to be resource-conscious, but usually not at the expense of your application design. That is probably the reason you were told not to throw your two Exceptions. Whether to use Exceptions or not usually boils down to how frequently the Exception will occur. If it's a fairly common or an fairly expectable result, this is when most developers will avoid Exceptions and instead create another method to indicate failure, because of the supposed consumption of resources.
Here's an example of avoiding using Exceptions in a scenario like just described, using the Try() pattern:
public class ValidatedLogin
{
public readonly string User;
public readonly string Password;
public ValidatedLogin(string user, string password)
{
if (IsInvalidUser(user))
{
throw new UserInvalidException(user);
}
else if (IsInvalidPassword(user, password))
{
throw new PasswordInvalidException(password);
}
this.User = user;
this.Password = password;
}
public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
{
if (IsInvalidUser(user) ||
IsInvalidPassword(user, password))
{
return false;
}
validatedLogin = new ValidatedLogin(user, password);
return true;
}
}
for me Exception should be thrown when a required technical or business rule fails.
for instance if a car entity is associated with array of 4 tires ... if one tire or more are null ... an exception should be Fired "NotEnoughTiresException" , cuz it can be caught at different level of the system and have a significant meaning through logging.
besides if we just try to flow control the null and prevent the instanciation of the car .
we might never never find the source of the problem , cuz the tire isn't supposed to be null in the first place .
the main reason for avoiding throwing an exception is that there is a lot of overhead involved with throwing an exception.
One thing the article below states is that an exception is for an exceptional conditions and errors.
A wrong user name is not necessarily a program error but a user error...
Here is a decent starting point for exceptions within .NET:
http://msdn.microsoft.com/en-us/library/ms229030(VS.80).aspx
Throwing exceptions causes the stack to unwind, which has some performance impacts (admitted, modern managed environments have improved on that). Still repeatedly throwing and catching exceptions in a nested situation would be a bad idea.
Probably more important than that, exceptions are meant for exceptional conditions. They should not be used for ordinary control flow, because this will hurt your code's readability.
I have three type of conditions that I catch.
Bad or missing input should not be an exception. Use both client side js and server side regex to detect, set attributes and forward back to the same page with messages.
The AppException. This is usually an exception that you detect and throw with in your code. In other words these are ones you expect (the file does not exist). Log it, set the message, and forward back to the general error page. This page usually has a bit of info about what happened.
The unexpected Exception. These are the ones you don't know about. Log it with details and forward them to a general error page.
Hope this helps
Security is conflated with your example: You shouldn't tell an attacker that a username exists, but the password is wrong. That's extra information you don't need to share. Just say "the username or password is incorrect."
I have philosophical problems with the use of exceptions. Basically, you are expecting a specific scenario to occur, but rather than handling it explicitly you are pushing the problem off to be handled "elsewhere." And where that "elsewhere" is can be anyone's guess.
To my mind, the fundamental question should be whether one would expect that the caller would want to continue normal program flow if a condition occurs. If you don't know, either have separate doSomething and trySomething methods, where the former returns an error and the latter does not, or have a routine that accepts a parameter to indicate whether an exception should be thrown if it fails). Consider a class to send commands to a remote system and report responses. Certain commands (e.g. restart) will cause the remote system to send a response but then be non-responsive for a certain length of time. It is thus useful to be able to send a "ping" command and find out whether the remote system responds in a reasonable length of time without having to throw an exception if it doesn't (the caller would probably expect that the first few "ping" attempts would fail, but one would eventually work). On the other hand, if one has a sequence of commands like:
exchange_command("open tempfile");
exchange_command("write tempfile data {whatever}");
exchange_command("write tempfile data {whatever}");
exchange_command("write tempfile data {whatever}");
exchange_command("write tempfile data {whatever}");
exchange_command("close tempfile");
exchange_command("copy tempfile to realfile");
one would want failure of any operation to abort the whole sequence. While one could check each operation to ensure it succeeded, it's more helpful to have the exchange_command() routine throw an exception if a command fails.
Actually, in the above scenario it may be helpful to have a parameter to select a number of failure-handling modes: never throw exceptions, throw exceptions for communication errors only, or throw exceptions in any cases where a command does not return a "success" indication.
You may use a little bit generic exceptions for that conditions. For e.g. ArgumentException is meant to be used when anything goes wrong with the parameters to a method (with the exception of ArgumentNullException). Generally you would not need exceptions like LessThanZeroException, NotPrimeNumberException etc. Think of the user of your method. The number of the conditions that she will want to handle specifically is equal to the number of the type of the exceptions that your method needs to throw. This way, you can determine how detailed exceptions you will have.
By the way, always try to provide some ways for users of your libraries to avoid exceptions. TryParse is a good example, it exists so that you don't have to use int.Parse and catch an exception. In your case, you may want to provide some methods to check if user name is valid or password is correct so your users (or you) will not have to do lots of exception handling. This will hopefully result in more readble code and better performance.
Ultimately the decision comes down to whether it is more helpful to deal with application-level errors like this using exception handling, or via your own home-rolled mechanism like returning status codes. I don't think there's a hard-and-fast rule about which is better, but I would consider:
Who's calling your code? Is this a public API of some sort or an internal library?
What language are you using? If it's Java, for example, then throwing a (checked) exception puts an explicit burden on your caller to handle this error condition in some way, as opposed to a return status which could be ignored. That could be good or bad.
How are other error conditions in the same application handled? Callers won't want to deal with a module that handles errors in an idiosyncratic way unlike anything else in the system.
How many things can go wrong with the routine in question, and how would they be handled differently? Consider the difference between a series of catch blocks that handle different errors and a switch on an error code.
Do you have structured information about the error you need to return? Throwing an exception gives you a better place to put this information than just returning a status.
Some useful things to think about when deciding whether an exception is appropriate:
what level of code you want to have run after the exception candidate occurs - that is, how many layers of the call stack should unwind. You generally want to handle an exception as close as possible to where it occurs. For username/password validation, you would normally handle failures in the same block of code, rather than letting an exception bubble up. So an exception is probably not appropriate. (OTOH, after three failed login attempts, control flow may shift elsewhere, and an exception may be appropriate here.)
Is this event something you would want to see in an error log? Not every exception is written to an error log, but it's useful to ask whether this entry in an error log would be useful - i.e., you would try to do something about it, or would be the garbage you ignore.
"PasswordNotCorrectException" isn't a good example for using exceptions. Users getting their passwords wrong is to be expected, so it's hardly an exception IMHO. You probably even recover from it, showing a nice error message, so it's just a validity check.
Unhandled exceptions will stop the execution eventually - which is good. If you're returning false, null or error codes, you will have to deal with the program's state all by yourself. If you forget to check conditions somewhere, your program may keep running with wrong data, and you may have a hard time figuring out what happened and where.
Of course, you could cause the same problem with empty catch statements, but at least spotting those is easier and doesn't require you to understand the logic.
So as a rule of thumb:
Use them wherever you don't want or simply can't recover from an error.
I would say that exceptions should be thrown if an unexpected behaviour is occuring that wasnt meant to be.
Like trying to update or delete a non existing entity. And it should be catched where the Exception can be handled and has meaning. For working in an alternative way to continue, add logging or returning a specific result on Api level.
If you expect something to be the case, you should build code to check and ensure it.