Skip to main content

Differentiate Proximate and Root Causes

Say a bug happens in some code, perhaps

Cannot call toUpperCase on undefined: line 15

What’s the cause of the bug, and how do we fix it? Do we go to line 15, and add a check for undefined with some kind of default value? That will make the error go away, right?

The correct question to ask at this point is “why is the value we’re calling toUpperCase on undefined in the first place? Is this expected behaviour? Or did some upstream code pass undefined even though we were expecting a defined value?

“Proximate” cause of a bug is a cause closest to where the error actually occurred. In this case, the bug was calling a function on undefined, so the proximate cause is “the value was undefined, and we called a function without first making sure it’s defined”.

“Root” cause of a bug is often a few hops away, and is more subtle to track down. Someone further up the call stack, for some reason, is passing an undefined value. Perhaps the value is coming from the database, and the column happened to be nullable, even though it shouldn’t be, and some code ended up writing a null value in to it, even though it shouldn’t have. The column being nullable is still merely a “proximate” cause, since column nullability is just a safety mechanism — it’ll help catch errors earlier, but you still have to manually ensure that the data you actually put in does not contain nulls. So how did the null get into the database?

You should always strive to fully understand the root cause of a bug.

Once you do understand, what you do about it depends on context. Sometimes a quick fix to the proximate cause, deployed to production to prevent user-facing errors, followed by a more slowly executed, thorough root cause fix, is the right thing to do. At other times, no stopgaps, and only fix of the root cause, will do. But the key point here is that understanding the root cause is not a corner you should ever cut.

Root versus proximate is a dichotomy that comes up in many domains, not just debugging. I was stopped by a cop for crossing a street when the light was red the other day. He thoroughly scolded me about disobeying rules. But the rule in itself is pointless. It only exists to ensure the safety of drivers and pedestrians. So whether the rule itself is obeyed or not is irrelevant as long as the root goal of the rule is fulfilled — the road had good visibility and was empty, so I was safe, and no small children were watching me and thus risking developing bad habits before they develop judgement. The rule is proximate, the goal it’s supposed to achieve is root.

In the next section we discuss a common technique for tracking down the root cause.

Next: Ask “Why?” Until Your Reach The Root ⇒

Comments