# sol2 3.5.0 documentation

## exceptions

### Search the Documentation

# exceptions

## since somebody is going to ask about it…

Yes, you can turn off exceptions in sol with `#define SOL_NO_EXCEPTIONS` before including or by passing the command line argument that defines `SOL_NO_EXCEPTIONS`. We don’t recommend it unless you’re playing with a Lua distro that also doesn’t play nice with exceptions (like non-x64 versions of LuaJIT ).

If you turn this off, the default at_panic function state set for you will not throw (see sol::state’s automatic handlers for more details). Instead, the default Lua behavior of aborting will take place (and give you no chance of escape unless you implement your own at_panic function and decide to try `longjmp` out).

To make this not be the case, you can set a panic function directly with `lua_atpanic( lua, my_panic_function );` or when you create the `sol::state` with `sol::state lua(my_panic_function);`. Here’s an example `my_panic_function` you can have that prints out its errors:

typical panic function

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3#include <iostream>
     4
     5inline void my_panic(sol::optional<std::string> maybe_msg) {
     6	std::cerr << "Lua is in a panic state and will now abort() "
     7	             "the application"
     8	          << std::endl;
     9	if (maybe_msg) {
    10		const std::string& msg = maybe_msg.value();
    11		std::cerr << "\terror message: " << msg << std::endl;
    12	}
    13	// When this function exits, Lua will exhibit default
    14	// behavior and abort()
    15}
    16
    17int main(int, char*[]) {
    18	sol::state lua(sol::c_call<decltype(&my_panic), &my_panic>);
    19	// or, if you already have a lua_State* L
    20	// lua_atpanic( L, sol::c_call<decltype(&my_panic),
    21	// &my_panic> ); or, with state/state_view: sol::state_view
    22	// lua(L); lua.set_panic( sol::c_call<decltype(&my_panic),
    23	// &my_panic> );
    24
    25	// uncomment the below to see
    26	// lua.script("boom_goes.the_dynamite");
    27
    28	return 0;
    29}

Note that `SOL_NO_EXCEPTIONS` will also disable sol::protected_function’s ability to catch C++ errors you throw from C++ functions bound to Lua that you are calling through that API. So, only turn off exceptions in sol if you’re sure you’re never going to use exceptions ever. Of course, if you are ALREADY not using Exceptions, you don’t have to particularly worry about this and now you can use sol!

If there is a place where a throw statement is called or a try/catch is used and it is not hidden behind a `#ifndef SOL_NO_EXCEPTIONS` block, please file an issue at issue or submit your very own pull request so everyone can benefit!

## various sol and lua handlers

Lua comes with two kind of built-in handlers that sol provides easy opt-ins for. One is the `panic` function, as demonstrated above. Another is the `pcall` error handler, used with sol::protected_function. It is any function that takes a single argument. The single argument is the error type being passed around: in Lua, this is a single string message:

regular error handling

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4#include <iostream>
     5
     6int main() {
     7	std::cout << "=== protected_functions ===" << std::endl;
     8
     9	sol::state lua;
    10	lua.open_libraries(sol::lib::base);
    11
    12	// A complicated function which can error out
    13	// We define both in terms of Lua code
    14
    15	lua.script(R"(
    16			function handler (message)
    17				return "Handled this message: " .. message
    18			end
    19
    20			function f (a)
    21				if a < 0 then
    22					error("negative number detected")
    23				end
    24				return a + 5
    25			end
    26		)");
    27
    28	// Get a protected function out of Lua
    29	sol::protected_function f(lua["f"], lua["handler"]);
    30
    31	sol::protected_function_result result = f(-500);
    32	if (result.valid()) {
    33		// Call succeeded
    34		int x = result;
    35		std::cout << "call succeeded, result is " << x
    36		          << std::endl;
    37	}
    38	else {
    39		// Call failed
    40		sol::error err = result;
    41		std::string what = err.what();
    42		std::cout << "call failed, sol::error::what() is "
    43		          << what << std::endl;
    44		// 'what' Should read
    45		// "Handled this message: negative number detected"
    46	}
    47
    48	std::cout << std::endl;
    49}

The other handler is specific to sol2. If you open a `sol::state`, or open the default state handlers for your `lua_State*` (see sol::state’s automatic handlers for more details), there is a `sol::exception_handler_function` type. It allows you to register a function in the event that an exception happens that bubbles out of your functions. The function requires that you push 1 item onto the stack that will be used with a call to lua_error

exception handling

     1#define SOL_ALL_SAFETIES_ON 1
     2#include <sol/sol.hpp>
     3
     4
     5#include <iostream>
     6
     7int my_exception_handler(lua_State* L,
     8     sol::optional<const std::exception&> maybe_exception,
     9     sol::string_view description) {
    10	// L is the lua state, which you can wrap in a state_view if
    11	// necessary maybe_exception will contain exception, if it
    12	// exists description will either be the what() of the
    13	// exception or a description saying that we hit the
    14	// general-case catch(...)
    15	std::cout << "An exception occurred in a function, here's "
    16	             "what it says ";
    17	if (maybe_exception) {
    18		std::cout << "(straight from the exception): ";
    19		const std::exception& ex = *maybe_exception;
    20		std::cout << ex.what() << std::endl;
    21	}
    22	else {
    23		std::cout << "(from the description parameter): ";
    24		std::cout.write(description.data(),
    25		     static_cast<std::streamsize>(description.size()));
    26		std::cout << std::endl;
    27	}
    28
    29	// you must push 1 element onto the stack to be
    30	// transported through as the error object in Lua
    31	// note that Lua -- and 99.5% of all Lua users and libraries
    32	// -- expects a string so we push a single string (in our
    33	// case, the description of the error)
    34	return sol::stack::push(L, description);
    35}
    36
    37void will_throw() {
    38	throw std::runtime_error("oh no not an exception!!!");
    39}
    40
    41int main() {
    42	std::cout << "=== exception_handler ===" << std::endl;
    43
    44	sol::state lua;
    45	lua.open_libraries(sol::lib::base);
    46	lua.set_exception_handler(&my_exception_handler);
    47
    48	lua.set_function("will_throw", &will_throw);
    49
    50	sol::protected_function_result pfr = lua.safe_script(
    51	     "will_throw()", &sol::script_pass_on_error);
    52
    53	SOL_ASSERT(!pfr.valid());
    54
    55	sol::error err = pfr;
    56	std::cout << err.what() << std::endl;
    57
    58	std::cout << std::endl;
    59
    60	return 0;
    61}

## LuaJIT and exceptions

It is important to note that a popular 5.1 distribution of Lua, LuaJIT, has some serious caveats regarding exceptions. LuaJIT’s exception promises are flaky at best on x64 (64-bit) platforms, and entirely terrible on non-x64 (32-bit, ARM, etc.) platforms. The trampolines we have in place for all functions bound through conventional means in sol will catch exceptions and turn them into Lua errors so that LuaJIT remainds unperturbed, but if you link up a C function directly yourself and throw, chances are you might have screwed the pooch.

Testing in this closed issue that it doesn’t play nice on 64-bit Linux in many cases either, especially when it hits an error internal to the interpreter (and does not go through sol). We do have tests, however, that compile for our continuous integration check-ins that check this functionality across several compilers and platforms to keep you protected and given hard, strong guarantees for what happens if you throw in a function bound by sol. If you stray outside the realm of sol’s protection, however… Good luck.

## Lua and LuaJIT C++ Exception Full Interoperability

You can `#define SOL_EXCEPTIONS_SAFE_PROPAGATION` before including sol or define `SOL_EXCEPTIONS_SAFE_PROPAGATION` on the command line if you know your implmentation of Lua has proper unwinding semantics that can be thrown through the version of the Lua API you have built / are using.

This will prevent sol from catching `(...)` errors in platforms and compilers that have full C++ exception interoperability. This means that Lua errors can be caught with `catch (...)` in the C++ end of your code after it goes through Lua, and exceptions can pass through the Lua API and Stack safely.

Currently, the only known platform to do this is the listed “Full” platforms for LuaJIT and Lua compiled as C++. This define is turned on automatically for compiling Lua as C++ and `SOL_USING_CXX_LUA` (or `SOL_USING_CXX_LUA_JIT`) is defined.

Warning

`SOL_EXCEPTIONS_SAFE_PROPAGATION` is not defined automatically when sol detects LuaJIT. It is your job to define it if you know that your platform supports it!