Error Handling

Conduit’s APIs emit three types of messages for logging and error handling:

Message Type Description
Info General Information
Warning Recoverable Error
Error Fatal Error

Default Error Handlers

Conduit provides a default handler for each message type:

Message Type Default Action
Info Prints the message to standard out
Warning Throws a C++ Exception (conduit::Error instance)
Error Throws a C++ Exception (conduit::Error instance)

Using Custom Error Handlers

The conduit::utils namespace provides functions to override each of the three default handlers with a method that provides the following signature:

void my_handler(const std::string &msg,
                const std::string &file,
                int line)
{
  // your handling code here ...
}

conduit::utils::set_error_handler(my_handler);

Here is an example that re-wires all three error handlers to print to standard out:

//-----------------------------------------------------------------------------
void my_info_handler(const std::string &msg,
                     const std::string &file,
                     int line)
{
    std::cout << "[INFO] " << msg << std::endl;
}

void my_warning_handler(const std::string &msg,
                        const std::string &file,
                        int line)
{
    std::cout << "[WARNING!] " << msg << std::endl;
}

void my_error_handler(const std::string &msg,
                      const std::string &file,
                      int line)
{
    std::cout << "[ERROR!] " << msg << std::endl;
    // errors are considered fatal, aborting or unwinding the 
    // call stack with an exception are the only viable options
    throw conduit::Error(msg,file,line);
}
// rewire error handlers
conduit::utils::set_info_handler(my_info_handler);
conduit::utils::set_warning_handler(my_warning_handler);
conduit::utils::set_error_handler(my_error_handler);

// emit an example info message
CONDUIT_INFO("An info message");

Node n;
n["my_value"].set_float64(42.0);

// emit an example warning message

// using "as" for wrong type emits a warning, returns a default value (0.0)
float32 v = n["my_value"].as_float32();

// emit an example error message

try
{
    // fetching a non-existant path from a const Node emits an error
    const Node &n_my_value = n["my_value"];
    n_my_value["bad"];
}
catch(conduit::Error e)
{
    // pass
}
[INFO] An info message
[WARNING!] Node::as_float32() const -- DataType float64 at path my_value does not equal expected DataType float32
[ERROR!] Cannot fetch_existing, Node(my_value) is not an object

Using Restoring Default Handlers

The default handlers are part of the conduit::utils interface, so you can restore them using:

// restore default handlers
conduit::utils::set_info_handler(conduit::utils::default_info_handler);
conduit::utils::set_warning_handler(conduit::utils::default_warning_handler);
conduit::utils::set_error_handler(conduit::utils::default_error_handler);

Accessing Current Handlers

You can access the currently active handlers using the conduit::utils::info_handler(), conduit::utils::warning_handler(), and conduit::utils::error_handler() methods. Here is an example that shows how to save the current handlers, temporarily restore the default handlers, execute an operation, and finally restore the saved handlers:

// store current handlers
conduit::utils::conduit_info_handler    on_info  = conduit::utils::info_handler();
conduit::utils::conduit_warning_handler on_warn  = conduit::utils::warning_handler();
conduit::utils::conduit_error_handler   on_error = conduit::utils::error_handler();

// temporarily restore default handlers
conduit::utils::set_info_handler(conduit::utils::default_info_handler);
conduit::utils::set_warning_handler(conduit::utils::default_warning_handler);
conduit::utils::set_error_handler(conduit::utils::default_error_handler);

// do something exciting ...

// done with excitement, reset to previously saved handlers
conduit::utils::set_info_handler(on_info);
conduit::utils::set_warning_handler(on_warn);
conduit::utils::set_error_handler(on_error);