78

I thought about it and could not come up with an example. Why would somebody want to catch an exception and do nothing about it? Can you give an example? Maybe it is just something that should never be done.

ysolik
  • 6,340
  • 4
  • 34
  • 50

15 Answers15

89

I do it all the time with things like conversion errors in D:

import std.conv, std.stdio, std.exception;

void main(string[] args) {  
    enforce(args.length > 1, "Usage:  foo.exe filename");

    double[] nums;

    // Process a text file with one number per line into an array of doubles,
    // ignoring any malformed lines.
    foreach(line; File(args[1]).byLine()) {
        try {
            nums ~= to!double(line);
        } catch(ConvError) {
            // Ignore malformed lines.
        }
    }

    // Do stuff with nums.
}

That said, I think that all catch blocks should have something in them, even if that something is just a comment explaining why you are ignoring the exception.

Edit: I also want to emphasize that, if you're going to do something like this, you should be careful to only catch the specific exception you want to ignore. Doing a plain old catch {} is almost always a bad thing.

dsimcha
  • 17,224
  • 9
  • 64
  • 81
  • Some IDEs allow you to specify that a particular name for the exception (usually "ignore") indicates that you are purposely ignoring it, which suppresses the warning it would otherwise show; this takes the place of the comment. – Alex Feinman Nov 04 '10 at 14:46
  • I'm not familiar D, but I assume it is possible to do something like bool TryParse(string line, out double valToParse), which may be cleaner. – ysolik Nov 04 '10 at 15:54
  • @ysolik: No, this isn't included in the std. lib. – dsimcha Nov 04 '10 at 16:06
  • @ysolik: I'd imagine that would wrap the parse function with a try and empty catch anyway... – JohnL Nov 04 '10 at 16:15
  • 4
    Like @Michael says -- it's not *quite* empty since you've got the comment there; it should be obligatory to add a "this catch intentionally left blank" comment if there isn't a statement – STW Nov 04 '10 at 20:54
  • +1 to "I think that all catch blocks should have something in them, even if that something is just a comment explaining why you are ignoring the exception." – Mike Clark Nov 04 '10 at 21:19
  • 1
    Showing or logging lines that failed to import is generally a useful feature... but an optional extra one, of course. – dbkk Nov 05 '10 at 04:53
  • 1
    Might not be relevant to the question, but using a try catch in that manner is bad business. Try/catch is slow. You're basically putting on the hand break in your app every time there's an exception, and in this case, for nothing. – Kelly Elton Feb 12 '13 at 00:51
  • @KellyElton If malformed lines are rare it could be more expensive to check (which happens every time) than to let it blow (which would only happen if it's malformed.) – Loren Pechtel Jan 01 '18 at 01:34
  • @LorenPechtel Yeah I agree with you. – Kelly Elton Jan 02 '18 at 22:54
54

One example where I think is OK to just swallow exception without doing anything, even logging the exception, is inside logging code itself.

If you tried to log something and got exception there is not much you can do about it:

  • you can not log it of course;
  • you might be able to fall back to a reserve logging mechanism, but most applications are not that sophisticated, and for those that are sophisticated enough the same design problem will arise with the reserve logging mechanism;
  • fast fail - will be too radical a solution for most applications;
  • throwing exception up will do little good as it will end up in a catch statement up the stack that will almost certain try to log it...

That leaves you with the "least of the evil" option of quietly swallowing it, allowing the application to keep performing its main job, but compromising the ability to troubleshoot it.

Kate Gregory
  • 17,465
  • 2
  • 50
  • 84
kdubinets
  • 731
  • 6
  • 6
  • 11
    great point. debugging the debugging code is always a challenge. – DevSolo Nov 04 '10 at 14:57
  • 8
    This, a million times. Especially when you consider that if you're logging, you may be in a terrible state; you could be out of memory, could be crashing, could be anything. At this point, when you're logging an error, and THAT fails, the only responsible thing to do is nothing; you have no guarantee that anything you try will not make it worse. – GWLlosa Nov 04 '10 at 19:55
  • Great point. In my logging code, I also like to add the InnerMessage for the exception. Many times this is null, so trying to add it would blow up the logging itself. – Tangurena Nov 05 '10 at 02:38
  • @Tangurena If it's often null then handle that, don't blow. In C# I often guard such things by ?? ""; – Loren Pechtel Jan 01 '18 at 01:43
8

If an exception is thrown by an operation that was optional anyway, there might be nothing to do. It might not be useful to log it. In that case, you may just want to catch it and do nothing.

If you're doing this, include a comment. Always comment anything that looks like a bug (fallthrough in a switch statement, empty catch block, assignment in a condition).

You might argue that this isn't a proper use of exceptions, but that's for another question.

David Thornley
  • 20,238
  • 2
  • 55
  • 82
6

As a general rule, no. You either want to throw the exception up the stack, or log what happened.

However, I often do this when I'm parsing strings and converting to numbers (especially in mapping projects that are of the use-once and throw away variety).

boolean isNonZeroNumber = false;

try {
   if(StringUtils.isNotBlank(s) && new BigDecimal(s).compareTo(BigDecimal.ZERO) != 0) {
     b = true;
   }
} catch(NumberFormatException e) {
//swallow this exception; b stays false.
}

return b;
Fil
  • 659
  • 4
  • 9
6

Empty catch blocks are a code smell in most languages. The main idea is to use exceptions for exceptional situations and not to use them for logical control. All exceptions must be handled somewhere.

As a consequence of taking this approach, when you program one particular application layer, you have several choices:

  • do nothing about the exception. It will be caught and handled by a different layer
  • catch it and perform the corrective action.
  • catch it, do something, but re-throw it for another layer to handle

This doesn't really leave any room for do-nothing, empty catch blocks.

EDITED TO ADD: suppose you are programming in a language where throwing exceptions is the normal way of controlling the program logic (one of alternatives to goto). Then an empty catch block in a program written in this language is very much like an empty else block in a traditional language (or no else block at all). However, I believe this is not the programming style recommended by C#, Java or C++ development communities.

azheglov
  • 7,177
  • 1
  • 27
  • 49
  • I think using exceptions as logic control has become fairly common, so I find myself with empty or nearly empty catch blocks quite often. – whatsisname Nov 04 '10 at 16:18
  • +1 for recognizing that an empty catch block *could* indicate use of exceptions for flow control. – John M Gant Nov 04 '10 at 16:57
  • Using exceptions for programming logic is generally considered to be bad practice. But, surprisingly (my original argument against exceptions) exceptions don't incur a noticeable performance hit. See http://www.codeproject.com/KB/exception/ExceptionPerformance.aspx. – Evan Plaice Nov 20 '10 at 01:42
  • I think your wording is a bit strong. There are legitimate scenarios where exception catches need no code. 1) An exception happened, the JWT couldn't be expired on logout; 2) Do nothing because the session is cleared locally and there is a hard 10 min timeout on tokens on the remote API; 3) No need to halt the code with a message to the user as their token will expire in 10 mins max and their session cleared locally means they are logged out; 4) It was already logged to error log up stream (service or other class) – James Jul 27 '20 at 10:06
6

In some cases, Java requires you to handle an exception that can, under absolutely no circumstances, ever happen. Consider this code:

try {
   bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}

Every implementation of the Java platform is required to support the following standard charsets.

...

UTF-8

Without breaking your Java platform, there is simply no way to ever cause this exception. So why bother handling it? But you cannot simply ommit the try-catch-clause.

user281377
  • 28,352
  • 5
  • 75
  • 130
  • 1
    In cases like this I would be tempted to add `throw new Error(e)` just to be absolutely sure that I didn't miss anything (or report actually broken platform). – bisgardo May 19 '17 at 08:09
  • @HalleKnast Yes. This has been discussed in full detail here: https://softwareengineering.stackexchange.com/questions/122233/how-to-deal-with-checked-exceptions-that-cannot-ever-be-thrown – user281377 May 19 '17 at 08:38
3

In some cases, the exception is not at all exceptional; in fact, it is expected. Consider this example:

    /* Check if the process is still alive; exitValue() throws an exception if it is */
    try {
        p.exitValue();
        processPool.remove(p);
    }
    catch (IllegalThreadStateException e) { /* expected behaviour */ }

Since there is no isAlive() method in java.lang.Process(), about the only way to check if it is still alive is to call exitValue(), which throws an IllegalThreadStateException if the process is still running.

user281377
  • 28,352
  • 5
  • 75
  • 130
2

In my humble experience, rarely is this good thing. You mileage may vary though.

Nearly every time I've seen this in our code base, it's been because I've tracked down a bug that the eaten exception has hidden. To put another way, by not providing any code, the application has no way of indicating an error, or performing another action.

Sometimes, at API layers for example, you might not want or be able to let exceptions past, so in that case, I tend to try and catch the most generic, then log those. Once again, to at least give a debug/diagnosis session a chance.

Typically, if it must be empty, the least I do is put an assertion of some kind, so at least something happens during a debug session. That said, if I can't handle it, I tend to omit them completely.

DevSolo
  • 2,814
  • 20
  • 23
2

IMO there is one place where empty catch statements are OK. In test cases where you expect an exception:

try
{
   DoSomething(); //This should throw exception if everything works well
   Assert.Fail('Expected exception was not thrown');
}
catch(<whatever exception>)
{
    //Expected to get here
}
Victor Hurdugaci
  • 3,243
  • 18
  • 20
2

I believe there are certain cases where it is justified to have an empty catch clause - these are cases when you want the code to just keep going if a particular operation fails. However, I do think that this pattern can be easily overused, so each use should be closely examined to make sure there's not a better way to handle it. In particular, this should never be done if it leaves the program in an inconsistent state or if it could lead to some other part of the code failing later on.

o. nate
  • 271
  • 2
  • 3
1

I don't believe in not having some level of alert when an exception occurs - shouldn't one of the goals of programming be to improve code? If an exception occurs 10% of the time, and you never know about it, then the exception will always be that bad, or worse.

However, I do see the other side, that if the exception does no real harm in the processing of code, then why expose the user to it. The solution I typically implement is having it logged by my logger class (that is in every single class I ever write at work).

If it's a benign exception, then I make a call to my Logger's .Debug() method; otherwise, Logger.Error() (and (maybe) throw).

try
{
   doWork();
}
catch(BenignException x)
{
  _log.Debug("Error doing work: " + x.Message);
}

By the way, in my implementation of my logger, making a call to the .Debug() method will only log it if I my App.Config file specifies that program execution log level is in Debug mode.

Tim Claason
  • 913
  • 7
  • 11
  • What if _log.Debug throws an exception (for whatever reason)? – JohnL Nov 04 '10 at 19:19
  • Then .Debug() eats the exception and I never know about it. But I feel a lot more confident about my logger than I feel about code that often throws exceptions. If I were concerned about that, I suppose I could implement some sort of pattern that watches for entry into the catch block, and saves it for later. In any case - point taken – Tim Claason Nov 04 '10 at 21:09
1

Existence checking is a good use case:

// If an exception happens, it doesn't matter. Log the initial value or the new value

function logId(person) {
    let id = 'No ID';
    try {
        id = person.data.id;
    } catch {}
    console.log(id);
}

Another case is when a finally clause is used:

 function getter(obj){}

 function objChecker()
   {
   try
     {
     /* Check argument length and constructor type */
     if (getter.length === 1 && getter.constructor === Function)
       {
       console.log("Correct implementation");
       return true;
       }
     else
       {
       console.log("Wrong implementation");
       return false;
       }
     }
   catch(e)
     {
     }
   finally
     {
     console.log(JSON.stringify(getter))
     }
   }

 // Test the override of the getter method 
 getter = getter;
 objChecker();
 getter = [];
 objChecker();
 getter = {};
 objChecker();
 getter = RegExp;
 objChecker();
 getter = Function;
 objChecker();

There is a proposal to allow the omission of the catch binding in ECMAScript which pertains to this and similar use cases.

References

Paul Sweatte
  • 382
  • 2
  • 15
  • Another example: In nodejs, the fs.exists method (which returns true or false) is deprecated (https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_fs_exists_path_callback) in favour of fs.access which throws an exception in case a file does not exist. If one wants to do something only if the file exists, the catch clause is totally unnecessary. – Geoffrey Jul 17 '19 at 06:01
0

The only time I've really needed to do something like this was with a logging class for a console app. There was a top-level global catch handler which emitted the error to STDOUT, logged the error to a file, then closed the app with a >0 error code.

The problem here was that sometimes, the logging to the file failed. Directory permissions stopped you from writing the file, the file was exclusively locked, whatever. If that happened, I couldn't handle the exception in the same way I had elsewhere (catch, log the relevant details, wrap in a better exception type, etc) because logging the exception details caused the logger to go through the same actions (trying to write to a file) which had already failed. When they failed again... You see where I'm going. It gets into an infinite loop.

If you drop some of the try {} blocks, you can end up with the exception appearing in a message box (not what you want for a silent config app). So in that method which writes to the log file, I have an empty catch handler. This doesn't bury the error since you still get the >0 error code, it just stops the infinite loop and allows the app to exit gracefully.

There's a comment of course, explaining why it's empty.

(I was going to post this earlier, I was just afraid of getting flamed into oblivion. Since I'm not the only one, though...)

JohnL
  • 1,890
  • 13
  • 14
0

It is ok in situation when some sequence must be executed no matter what with most critical piece placed at the end.

For example. In motion control communication of host to controller. In emergency situations there is a number of preparation steps to abort movement, stop trajectory generation, decelerate motors, enable breaks, disable amplifier and after this you must kill bus power. All must happen sequentially and if one of steps fails rest of steps must be executed anyway even with accepted risk of damaging hardware. Say even if all above fails, the kill bus power must happen anyway.

  • That doesn't mean you do nothing, just that what you do doesn't abort the flow. Catch your exceptions, save them **in memory** (no disk write delay), then kill the power in a finally statement. Then do what you will with the saved information. – Loren Pechtel Jan 01 '18 at 01:42
0

Closing out system resources gracefully to recover from an error

For instance. If you're running a service in the background that doesn't provide feedback to the user, you may not want to push an indication of the error to the user but you do need to close out the resources being used in a graceful manner.

try
{
    // execution code here
}
catch(Exception e)
{
    // do nothing here
}
finally
{
    // close db connection
    // close file io resource
    // close memory stream
    // etc...
}

Ideally, you'd use the catch in debug mode to catch errors and print them to the console or to a log file for testing. In a production environment, background services generally are expected to not interrupt the user when an error is thrown so the error output should be suppressed.

Evan Plaice
  • 5,725
  • 2
  • 24
  • 34