assert(): A modern How To
assert(): A modern How To
Reza Naghibi - August 3rd 2026
Something that has always bothered me has been the assert() statement. While I personally consider the simple assertion statement as part of the bedrock of correct, safe, and supportable software, I feel that it also has come up a bit short in some regards. First, a lot of assert() implementations are simply under powered. While they do provide a bit of useful information, these implementations stop short of providing deeper and more useful context. Second, it’s really confusing when you should even use an assertion. Is it a lightweight debugging statement? Can assertions be used in production? What should I be asserting on? Can I customize how assert behaves? This confusion is compounded by the fact that a handful of implementations even allow for all assertions to be disabled with a simple compile time switch. So taken together, I would say much work still needs to be done around proper assert() understanding and usage.
The first and most important step in understanding how to better leverage assert() is to define when and where these statements should be used. I'm going to outline four areas where assertions can be effective:
Correctness - All possible function input and output values which do not have full value coverage should have assertions covering them.
Safety - When performing operations that can have unwanted, known, or unknown side effects, assertions should be used to prevent those conditions from happening.
Development - Use an assertion to enforce assumptions on values and state. These assertions can optionally be compiled out of code when coupled with proper testing.
Documentation - When writing code, use assertions as self documenting guardrails around your logic. Use assertions to enforce values and state which might be unclear from documentation or hard to decipher from reading code.
The added bonus here is when assertions are properly used across your code, static analysis of your code can now become more effective. Assertions greatly narrow the scope for data validation and invariant analysis, allowing for better results. You might be wondering, won’t all these assertions make my code slow and bloated? The simple answer here is no, when used properly, assertions have little to no overhead. We are talking about just a few CPU cycles to read a local value and then skip over a branch, which for most applications cannot even be accurately measured. When evaluated against the benefits assertions are giving you, it’s hard to argue against them.
Correctness and Safety
So let's talk about correctness, because this is probably the most important and under utilized role for assertions. When writing code, it’s easy to overlook all the different potential values a parameter or return value can have. An assertion can fix that gap, simply assert that the value is what you expect. If you support every possible value, which is usually the case, then no assertion is needed. Between the logic and your assertion, all potential values should now be covered and we can now say that coverage for this value is “correct”.
For example, let’s say we have this logic where error values are correctly covered with an assertion:
var error = system_call(...);<br>assert(!error);
Now, let’s say an error is generated and returned. Your program crashes. Obviously this is not ideal behavior, common values, including errors, should be handled more gracefully. However, what’s important here are two things. First, you have been made aware that this asserted value does exist. You can now choose to take action on it, like making a code change to actually handle this value or maybe spend some time better understanding what happened. Second, and this is the more important point, you started off with 100% value correctness and continue to have 100% value correctness. A failed assertion is behaving exactly as you intended, it correctly caught an edge case. Had that assertion not existed or been compiled away, your application would be in unknown and unsafe territory.
Here is another example illustrating value correctness:
var x = random();<br>assert(x > 0);
We set the assertion condition that we expect x to be greater than zero and as long as the logic using x supports all possible values of x greater than zero, we can say we are correct here for x. Now, let's say for whatever reason random() gives us a zero or a negative number, the assertion tells us our assumption was wrong and the program immediately terminates. We now hopefully have the opportunity to rectify this error with better handling or at least an investigation of what went wrong. Again, if we wrote this code without the assertion and we encountered a zero or negative number, we now have unexpected behavior and even worse, we may not even know it’s happening.
A few common examples of hard to handle values might be when a memory allocation call fails. While there are some...