As many of you may know we work with a variety of programming languages and ecosystems with very different code bases. Sometimes it may be a modern green field project using state of the art frameworks. At other times it may be a dreaded legacy project initially written many years ago (either by us or someone we do not even know) using ancient languages and frameworks like really old java stuff (pre jdk 7) or C++ (pre C++11), for example.
These old projects could not use features of modern incarnations of these languages/compilers/environments – and that is fine with me. We usually gradually modernize such systems and try to update the places where we come along to fix some issues or implement new features.
Over the years I have come across a pattern that I think is dangerous and easily leads to bugs and harder to maintain code:
Special values of the resulting type of a function to indicate errors
The examples are so numerous and not confined to a certain programming environment that they urged me to write this article. Maybe some developers using this practice will change their mind and add a few tools to their box to write safer and more expressive code.
A simple example
Let us image a function that returns a simple integer number like this:
/**
* Here we talk to a hardware sensor. If everything works, we should
* get a value between -50 °C and +50 °C.
* If something goes wrong, we return -9999.
int readAmbientTemperature();
Given the documentation, clients can surely use this kind of function and if every use site interprets the result correctly, nothing will ever go wrong. The problem here is, that we need a lot of domain knowledge and that we have to check for the special value.
If we use this pattern for other values where the value range is not that clearly bounded we may either run into problems or invent other “impossible values” for each use case.
If we forget to check for the special value the users may see it an be confused or even worse it could be used in calculations.
The problem even gets worse with more flexible types like floating point numbers or strings where it is harder to compare and divide valid results from failure indicators.

Classic error message that mixes technical code and error message in a confusing, albeit funny sentence (Source: Interface Hall Of Shame)
Of course, there are slightly better alternatives like negative numbers in a positive-only domain function or MAX_INT
, NaN
or the like provided by most languages.
I do not find any of the above satisfying and good enough for production use.
Better alternatives
Many may argue, that their environment lacks features to implement distinct error indicators and values but I tend to disagree and would like to name a few widely used alternatives for very different languages and environments:
- Return codes and out-parameters for C-like languages like in the unix and win32 APIs (despite all their other flaws… 😀 )
- Exceptions for Java, Python, .NET and maybe in some cases even C++ with sufficiently specific type and details to differentiate different failures
- Optional return types when the failures do not need special handling and absence of a value is enough
- HTTP status code (e.g. 400 or 404) and a JSON object containing reason and details instead of a 2xx status with the value
- A result struct or object containing execution status and either a value on success or error details on failure
Conclusion
I am aware that I probably spent way too much words on such a basic topic but I think the number of times I have encountered such a style – especially in code of autodidacts, but also professionals – justifies such an article in my opinion. I hope I provided some inspiration for those who do not know better or those who want to help others improve.