# Exceptions

## Built-in exception translation

When C++ code invoked from Python throws an `std::exception`, it is automatically converted into a Python `Exception`. pybind11 defines multiple special exception classes that will map to different types of Python exceptions:

C++ exception type | Python exception type
--- | ---
`std::exception` | `RuntimeError`
`std::bad_alloc` | `MemoryError`
`std::domain_error` | `ValueError`
`std::invalid_argument` | `ValueError`
`std::length_error` | `ValueError`
`std::out_of_range` | `IndexError`
`std::range_error` | `ValueError`
`pybind11::stop_iteration` | `StopIteration` (used to implement custom iterators)
`pybind11::index_error` | `IndexError` (used to indicate out of bounds access in `__getitem__`, `__setitem__`, etc.)
`pybind11::value_error` | `ValueError` (used to indicate wrong value passed in `container.remove(...)`)
`pybind11::key_error` | `KeyError` (used to indicate out of bounds access in `__getitem__`, `__setitem__` in dict-like objects, etc.)
`pybind11::error_already_set` | Indicates that the Python exception flag has already been set via Python API calls from C++ code; this C++ exception is used to propagate such a Python exception back to Python.

When a Python function invoked from C++ throws an exception, it is converted into a C++ exception of type `error_already_set` whose string payload contains a textual summary.

There is also a special exception `cast_error` that is thrown by `handle::call()` when the input arguments cannot be converted to Python objects.

## Registering custom translators

If the default exception conversion policy described above is insufficient, pybind11 also provides support for registering custom exception translators. To register a simple exception conversion that translates a C++ exception into a new Python exception using the C++ exception’s `what()` method, a helper function is available:

    py::register_exception<CppExp>(module, "PyExp");

This call creates a Python exception class with the name `PyExp` in the given module and automatically converts any encountered exceptions of type `CppExp` into Python exceptions of type `PyExp`.

When more advanced exception translation is needed, the function `py::register_exception_translator(translator)` can be used to register functions that can translate arbitrary exception types (and which may include additional logic to do so). The function takes a stateless callable (e.g. a function pointer or a lambda function without captured variables) with the call signature `void(std::exception_ptr)`.

When a C++ exception is thrown, the registered exception translators are tried in reverse order of registration (i.e. the last registered translator gets the first shot at handling the exception).

Inside the translator, `std::rethrow_exception` should be used within a try block to re-throw the exception. One or more catch clauses to catch the appropriate exceptions should then be used with each clause using `PyErr_SetString` to set a Python exception or `ex(string)` to set the python exception to a custom exception type (see below).

To declare a custom Python exception type, declare a `py::exception` variable and use this in the associated exception translator (note: it is often useful to make this a static declaration when using it inside a lambda expression without requiring capturing).

The following example demonstrates this for a hypothetical exception classes `MyCustomException` and `OtherException`: the first is translated to a custom python exception `MyCustomError`, while the second is translated to a standard python RuntimeError:

    static py::exception<MyCustomException> exc(m, "MyCustomError");
    py::register_exception_translator([](std::exception_ptr p) {
        try {
            if (p) std::rethrow_exception(p);
        } catch (const MyCustomException &e) {
            exc(e.what());
        } catch (const OtherException &e) {
            PyErr_SetString(PyExc_RuntimeError, e.what());
        }
    });

Multiple exceptions can be handled by a single translator, as shown in the example above. If the exception is not caught by the current translator, the previously registered one gets a chance.

If none of the registered exception translators is able to handle the exception, it is handled by the default converter as described in the previous section.

See also

The file `tests/test_exceptions.cpp` contains examples of various custom exception translators and custom exception types.

Note

You must call either `PyErr_SetString` or a custom exception’s call operator (`exc(string)`) for every exception caught in a custom exception translator. Failure to do so will cause Python to crash with `SystemError: error return without exception set`.

Exceptions that you do not plan to handle should simply not be caught, or may be explicitly (re-)thrown to delegate it to the other, previously-declared existing exception translators.