Errors and Warnings [C++]

Module developers may also leverage the Cyclus error and warning system within the code that they write. These are useful for failing gracefully from undefined behavior or to signal that code is still experimental and under development.

Note

Python agents should just use the Python error and warning system.

Errors

Cyclus uses standard C++ execptions to throw and catch errors. However, whenever you #include "cyclus.h" or #include "error.h" you have access to a suite of exceptions that the kernel itself knows about. Table I. Cyclus Error Classes displays all of the Cyclus errors which live within the cyclus namespace and subclass from std::exception.

Table I. Cyclus Error Classes

Error

Description

Error

Base error for Cyclus.

ValueError

For values that are too big, too small, etc.

KeyError

For failed retrieval/insertion of key-based data into/from data structures.

StateError

For failed object state expectations.

IOError

For failed reading/writing to files, network connections, etc.

CastError

For failed casts that shouldn’t.

ValidationError

For validating files received via I/O or for indicating that the software has not been properly benchmarked.


For example, if a reactor finds itself with a negative flux in its Tock() function then it could choose to throw either a ValueError or a StateError. If the flux happened to be a state variable a StateError would be more appropriate. This would be implemented as follows:

Error example:

void Reactor::Tock(int time) {
  if (flux < 0.0)
    throw cyclus::StateError("negative fluxes are impossible!");
}

Warnings

Along with errors, there are corresponding non-terminal warning messages that modules may issue. These print messages to sdterr along with the kind of warning that was given. All warnings are issued through the cyclus::Warn<T>() function. This functions is templated on the cyclus::Warnings enum whose values and meanings may be seen in Table II. Cyclus Warnings.

Table II. Cyclus Warnings

Warnings

Description

WARNING

Basic warning for Cyclus.

VALUE_WARNING

For values that are too big, too small, etc.

KEY_WARNING

For unexpected retrieval/insertion of key-based data into/from data structures.

STATE_WARNING

For unexpected object state.

IO_WARNING

For unexpected reading/writing to files, network connections, etc.

CAST_WARNING

For unexpected casts.

VALIDATION_WARNING

For validating files received via I/O or for indicating that the software has not been properly benchmarked.

DEPRECATION_WARNING

For features, behaviors, or APIs that are no longer supported. Expect removal in future releases.

PENDING_DEPRECATION_WARNING

For features, behaviors, or APIs that are candidates for future deprecation.

EXPERIMENTAL_WARNING

For features, behaviors, or APIs that are not considered stable. Reasons for instability may include a lack of benchmarking, uncertainty about future needs, or known future API changes.


Revisiting the reactor error example from above, we could have issued a warning instead.

Warning example:

void Reactor::Tock(int time) {
  if (flux < 0.0)
    cyclus::Warn<cyclus::STATE_WARNING>("negative fluxes are impossible!");
}

Warnings have a number of advantages over errors. The first is that since they do not stop the process they are fast to issue. They are also a great way for communicating with users the expectations of using your module.

Warnings also have two command line options that users can provide which modify their behavior. The first is --warn-limit. This changes the maximum number of times a warning of each kind will be issued before further warnings are suppressed. This defaults to 1. A value of zero means to suppress all warnings and a very large number will print them all. For example, if the user wished to print the first 42 warnings of each kind they would call Cyclus as follows:

$ cyclus --warn-limit 42 ...

The second command line argument that alters warning behavior is --warn-as-error. This turns all warnings into corresponding error types and throws the error. This is useful for ensuring that only stable code is executed or to help uncover what is causing a warning to be thrown. It takes no arguments:

$ cyclus --warn-as-error ...