Avoid speculative error handling

Posted on

A general heuristic I’ve learned from reading, writing, and debugging a lot of code is don’t try to predict whether a future operation will fail. This comes up a lot when handling error conditions.

For example, I’ve seen plenty of code that reads something like this (pseudocode):

if not file_exists("input"):
  print("Input file not found")
else:
  input = open("input")

# or...

if not server_online("192.168.32.7"):
  print("Server is offline")
else:
  get_data("192.168.32.7")

It’s great to show friendly error messages like “Input file not found” or “Server is offline”, but the order of operations above is buggy!

The problem with the first case is that even if the file exists when it’s first checked, someone could delete or move it before the second statement executes. In the second case, a network cable could be unplugged.

It would be better to write the code as:

try input = open("input")
catch FileNotFound:
  print("Input file not found")

# and

try get_data("192.168.32.7")
catch ServerOffline:
  print("Server is offline")

Instead of checking whether something might not work before deciding whether to try at all, it’s usually better to just do the thing with the expectation that it might not work.

There are situations where it really does make sense to try to catch things early, but it seems much more common for this type of “speculative error handling” to cause problems than provide solutions.