Error Codes
by havoc
API design rule: error codes alone are not a reasonable way to report
errors.
You need a mechanism that can return a helpful string. Like
exceptions in most languages, or GError
in C. You can return an error code also, if appropriate.
A helpful string does NOT mean some generic string form of the error
code, as with strerror().
Here is an example from XPCOM (have to pick on someone, and this is
what I tripped on today):
Error: [Exception... "'Component does not have requested interface' when calling method: [nsIFactory::createInstance]" nsresult: "0x80004002 (NS_NOINTERFACE)" location: "<unknown>" data: no]
Wouldn’t it be helpful to know which interface was requested, deep
inside the app someplace? I vote yes. But XPCOM doesn’t have exceptions with
messages, it has error codes. (The least helpful error code, of course, is
NS_FAILED. NS_NOINTERFACE is a little bit helpful.)
Any number of APIs manage to screw this up. X11 protocol:
guilty. SQLite: guilty. Cairo: guilty. OpenGL: guilty. I’m sure there
are dozens more.
All of the above leave programmers reading docs and tracing code to
figure out mysterious error codes, for errors that would have been
obvious given some more context in a string. In C, the function you use
to set/report/throw an error should take a format string like
printf(), so it’s easy to add context.
Unless you’re writing something very low-level and
performance-critical, like a system call, error codes are always
wrong. If an API is simple and well-specified enough, error codes can
be sufficiently clear. But, none of X11, Cairo, XPCOM, SQLite, or
OpenGL qualify for simple enough.
Error codes have one other nasty problem: people start to overload
existing codes to mean many different things, because they’re
reluctant to add new codes or because new codes would break ABI. This
is visible in UNIX system calls, X11, and of course any API with a
generic “FAILED” code.
(This post was originally found at http://log.ometer.com/2008-07.html#4)