Error codes are often cryptic and nonsensical to the end-user, and they’re not much fun for the developer either. One problem I ran into was defining an error code numbering system. After some thought, I determined that I most wanted to avoid manual labour and typos, e.g. sequential numbering for an error code argument.
A linear sequence of numbers makes typos easy. Various sources of error, can crop up that way (e.g. “Oh! You meant error #23292 not #23291?”). The intent of distributing the numbers, is to make mistakes more apparent. It’s worth noting that I don’t intend to categorize the errors by numerical ranges, so that’s a non-issue. This is ond-and-a-half requirements in one: catch/avoid typos, catch/avoid communication errors.
Determining the error code for a new error condition should be painless. It’s tedious to find the next unused number out of the set of error codes – this is the repetitive, boring behaviour that computers are meant for.
Additional constraints I had:
- Code must always compile, and be in a state that properly indicates coding problems. I’m using Eclipse and like the code-completion and on-the-fly-compilation.
- Needs to work well for batch, as I had to back propagate the use of error codes to over 200 points where exceptions were being thrown.
My final solution follows. It creates a lot of auto-generated classes, but there’s a good reason that is explained later.
- The programmer uses the custom exception class
MyExceptionnormally. The programmer doesn’t need to think about error codes. - After check-in (for safety) of the working code, a search-and-replace program is run.
- The program finds all uses of classes named with the pattern
MyException_n, wherenis a number. This class is explained later. The set of these numbers are the error codes in use. - The program searches for throwing of the vanilla
MyException. For each occurrence a new, unused error code is generated and the call is replaced with the throwing of an auto-generatedMyException_xclass, wherexis the new error code. TheMyException_xclass is written out. - The modified code and new auto-generated exception classes are checked in.
MyException is a subclass of java.lang.Exception; while it has an error code field, it doesn’t provide a public way of setting the value. A single subclass of MyException exists initially, MyException_0. MyException_0 looks like its parent ctor signature-wise, but it sets the value of the error code based on its own class name.
When the program is replacing a call to throw a vanilla MyException, it makes a copy of MyException_0 and replaces all occurrences of zero with the new error code number. Since the implementation of MyException_0 uses its own class name to determine the error code value to set, this effectively changes the error code that will be seen at runtime. This means that every throw is using a different exception type.
Now, before the complexity drives readers away, the only reason for such hackery is the code formatter. The formatter moves the text around, so I can’t simply put in an error code of “42″ as a ctor argument to indicate an unassigned error, and do a search-and-replace on that. Thrown exceptions are recognized by “throw new XXX“, which is probably going to be on the same line, but the ctor arguments have a good chance of being on a different line. More generally, it’s that the Java language is flexible regarding whitespace/newlines and I don’t want to write anything that has to parse such variable data.
Rather than make the search-and-replace logic complex and prone to error, I am taking advantage of the fact that the class’s name can never be broken up. This makes the search-and-replace process simpler to implement and more robust against user error.
There are problems with this approach; it won’t work in every situation. OO-wise, it’s terrible; that’s mitigated by putting the generated exceptions in its own package. It’s also obvious these classes are not for direct consumption. Compilation takes a longer, but the additional load is a few seconds. The software is deployed in a single JAR, so I don’t have dependency concerns from putting all the auto-generated exceptions together.
While I’m sure it can fall apart or cause unacceptable constraints in other scenarios, for my scenario this approach adds a lot of value by automating a tedious and labour-intensive process. All without adding new restrictions on my environment/behaviour.
I’m happy with the result. I can develop as if I’d never heard of error codes. When I need to think about it, I blindly run an ant target, compile, test, check-in. Sixty seconds after start, I can go back to ignoring error codes.

