Return Codes (a.k.a. Status Codes)

Last update: 24 Oct 2018 [History] [Edit]

You may have noticed that your algorithm functions all return a code (typically StatusCode). You may have also noticed that we wrap some functions inside ANA_CHECK() inside this tutorial. Both of these are part of the error handling inside ATLAS code. The short summary is that if you call a function that returns a status code you should wrap it inside ANA_CHECK() and return a status code yourself. The details follow below.

Within ATLAS we have defined multiple classes for status codes (StatusCode, EL::StatusCode, xAOD::TReturnCode, CP::CorrectionCode, CP::SystematicCode) which all work mostly the same. If in doubt which type of status code to return StatusCode is typically a safe choice. Generally status codes have two or three possible values (though they have may different names):

  • SUCCESS: no error occurred. The function did all it promised to do.
  • FAILURE: an error occurred. By and large we should not assume we can continue at this point, and the best strategy is to print an error message saying what we are doing and return. Generally any function that returns FAILURE should also print an error message, even if it is only reporting that a function it called failed. That way it is a lot easier for the user to understand at what point the code failed.
  • RECOVERABLE: an error occurred but we may be able to proceed (with caution). This is only supported for some status codes, and it indicates that we ran into some situation that the code couldn’t handle, but we can still proceed, e.g. we tried to calibrate an object that is in a phase space region for which there are no calibration constants. If a function returns RECOVERABLE it should print out a warning message (even if it is just reporting that a function it called failed). Whether it is a good idea to proceed in these situations is a matter of debate (and somewhat situational).

If a function returns a status code you are required to check it. Depending on the type of status code and the settings for your job it may simply abort right then and there, print a warning message at the end of the job (see below), or do nothing. Since the default thing to do is to print an error message on failure and return failure, we provided the ANA_CHECK() macro which does it for you. In effect if you have a line like

ANA_CHECK (evtStore()->retrieve (eventInfo, "EventInfo"));

which is equivalent to doing something like

if (!evtStore()->retrieve (eventInfo, "EventInfo").isSuccess()) {
  ANA_MSG_ERROR (...);
  return StatusCode::FAILURE;
}

It is perfectly fine not to use ANA_CHECK() and just write the if-statements manually (e.g. to customize the error message), but by and large the ANA_CHECK macro results in more compact and readable code.

Changing the Return Type (optional/advanced)

Sometimes your function will return something other than a StatusCode, e.g. a EL::StatusCode. To accommodate that, you can change the return type for ANA_CHECK by adding this line at the beginning of the function:

ANA_CHECK_SET_TYPE (EL::StatusCode);

This tells ANA_CHECK() what type of status code to return. The default is StatusCode, so if your function returns anything else you need to specify it in this way.

Special note: You can use ANA_CHECK() inside your main() program as well if you specify:

int main ()
{
  using namespace asg::msgUserCode;
  ANA_CHECK_SET_TYPE (int);
  ...
}

This will then return a non-zero value on error (like main() should). Be warned that if you leave out ANA_CHECK_SET_TYPE (int); it will still compile, but return zero on error (which it shouldn’t). As a bug that is hard to catch, as it only occurs when another error occurs.

For some status codes not checking them will by default result in a warning message at the end of the program like this:

Warning in <xAOD::TReturnCode>:
Warning in <xAOD::TReturnCode>: Unchecked return codes encountered during the job
Warning in <xAOD::TReturnCode>: Number of unchecked successes: 502

If you actually want to track down where you forgot to check the status code that is not particularly helpful. So it is recommended instead to change the configuration so that instead unchecked status codes become hard errors at the point where you forgot to check them:

#ifdef ROOTCORE
#include <xAODRootAccess/tools/TReturnCode.h>
#include <AsgTools/StatusCode.h>
#endif
#include <PATInterfaces/CorrectionCode.h>
#include <PATInterfaces/SystematicCode.h>
...
#ifdef ROOTCORE
  xAOD::TReturnCode::enableFailure();
  StatusCode::enableFailure();
#endif
  CP::SystematicCode::enableFailure();
  CP::CorrectionCode::enableFailure();
...

Converting Failures to Exceptions (optional/advanced)

Sometimes you simply can not return a status code, e.g. because you are in a constructor which can not have a return type. For those cases you can do the check via:

ANA_CHECK_THROW (...);

Note that by and large this is strongly discouraged, and status codes should be used wherever possible. It is not that there is anything wrong with exceptions, but simply that using the same mechanism everywhere is a definite plus, particularly when it comes to error handling.

ANA_CHECK() vs. ATH_CHECK() (optional/advanced)

If you look at Athena code you will find that they use ATH_CHECK() instead of ANA_CHECK. There are a couple of differences between the two:

  • ANA_CHECK uses ANA_MSG_*, while ATH_CHECK uses ATH_MSG_*`. So all the comments on the differences between the two apply to the check macros as well.
  • ANA_CHECK can handle all kinds of status codes as well as boolean and pointer types for its argument. ATH_CHECK can only handle StatusCode itself.
  • It is possible to adjust the return type of ANA_CHECK e.g. to return a EL::StatusCode. ATH_CHECK will always return a StatusCode.

This can probably be summarized as saying that if you develop an Athena component and all you’ll ever see is a StatusCode then ATH_CHECK is probably the better choice, but in all other situations you should use ANA_CHECK.