# Uncaught errors ## Misbehaving methods Any function which returns `akerr_ErrorContext *` and completes successfully MUST call `SUCCEED_RETURN(errctx)`. Failure to do this may result in an invalid `akerr_ErrorContext *` being returned, which will cause an `AKERR_BEHAVIOR` error to be triggered from your code. ## Ensuring that all error codes are captured Any function which returns `akerr_ErrorContext *` should also be marked with `AKERR_NOIGNORE`. ```c akerr_ErrorContext AKERR_NOIGNORE *f(...); ``` This will cause a compile-time error if the return value of such a function is not used. "Used" here means assigned to a variable - it does not necessarily mean that the value is checked. However assuming that such functions are called inside of `ATTEMPT { ... }` blocks, it is safe to assume that such returns will be caught with `CATCH(...)`; therefore this error is a generally effective safeguard against careless coding where errors are not checked. Beware that `AKERR_NOIGNORE` is not a failsafe - it implements the `warn_unused_result` mechanic. By design users may explicitly ignore an error code from a function marked with `warn_unused_result` by explicitly casting the return to `void`. ```c #define AKERR_NOIGNORE __attribute__((warn_unused_result)) ``` ## Stack Traces Whenever an error is captured using the `FAIL_*` or `CATCH` methods, and is unhandled such that it manages to propagate all the way to the top of the caller stack without being managed, the last `FINISH` macro to touch the error will trigger a stack trace and kill the program. Consider the `tests/err_trace.c` program which intentionally triggers this behavior. It produces output like this: ``` tests/err_trace.c:func2:7: 1 (Null Pointer Error) : This is a failure in func2 tests/err_trace.c:func2:10 tests/err_trace.c:func1:18: Detected error 0 from array (refcount 1) tests/err_trace.c:func1:18 tests/err_trace.c:func1:21 tests/err_trace.c:main:30: Detected error 0 from array (refcount 1) tests/err_trace.c:main:30 tests/err_trace.c:main:33: Unhandled Error 1 (Null Pointer Error): This is a failure in func2 ``` From bottom to top, we have: * The last line printed is the `FINISH` macro call that triggered the stacktrace. * Above that, the `CATCH()` inside of `main()` which caught the exception from `func1()` but did not handle it * Above that, a statement that the error was detected in the `CATCH()` statement at the same line * Above that, the `FINISH()` macro in the `func1` method which detected the presence of an unhandled error and returned it up the calling stack * Above that, the `CATCH()` macro in the `func1` method which caught the error coming out of `func2()` * Above that, a statement that the error was detected in the `CATCH()` statement at the same line * Above that, the `FINISH()` macro in `func2()` which detected an unhandled error and passed it out of the function * Above that, a reference to the line where the `FAIL()` macro set the error code and provided the message which is printed here