# Chapter 5. Error handling

## 1. Error handling basics

igraph functions can run into various problems preventing them from normal operation. The user might have supplied invalid arguments, e.g. a non-square matrix when a square-matrix was expected, or the program has run out of memory while some more memory allocation is required, etc.

By default igraph aborts the program when it runs into an error. While this behavior might be good enough for smaller programs, it is without doubt avoidable in larger projects. Please read further if your project requires more sophisticated error handling. You can safely skip the rest of this chapter otherwise.

## 2. Error handlers

If igraph runs into an error - an invalid argument was supplied to a function, or we've ran out of memory - the control is transferred to the error handler function.

The default error handler is `igraph_error_handler_abort` which prints an error message and aborts the program.

The `igraph_set_error_handler()` function can be used to set a new error handler function of type `igraph_error_handler_t`; see the documentation of this type for details.

There are two other predefined error handler functions, `igraph_error_handler_ignore` and `igraph_error_handler_printignore`. These deallocate the temporarily allocated memory (more about this later) and return with the error code. The latter also prints an error message. If you use these error handlers you need to take care about possible errors yourself by checking the return value of (almost) every non-void igraph function.

Independently of the error handler installed, all functions in the library do their best to leave their arguments semantically unchanged if an error happens. By semantically we mean that the implementation of an object supplied as an argument might change, but its “meaning” in most cases does not. The rare occasions when this rule is violated are documented in this manual.

### 2.1. `igraph_error_handler_t` — The type of error handler functions.

    typedef void igraph_error_handler_t (const char *reason, const char *file,
                                         int line, igraph_error_t igraph_errno);

This is the type of the error handler functions.

Arguments:

`reason`: | Textual description of the error.
`file`: | The source file in which the error is noticed.
`line`: | The number of the line in the source file which triggered the error
`igraph_errno`: | The igraph error code.

### 2.2. `igraph_error_handler_abort` — Abort program in case of error.

    IGRAPH_EXPORT igraph_error_handler_t igraph_error_handler_abort;

The default error handler, prints an error message and aborts the program.

### 2.3. `igraph_error_handler_ignore` — Ignore errors.

    IGRAPH_EXPORT igraph_error_handler_t igraph_error_handler_ignore;

This error handler frees the temporarily allocated memory and returns with the error code.

### 2.4. `igraph_error_handler_printignore` — Print and ignore errors.

    IGRAPH_EXPORT igraph_error_handler_t igraph_error_handler_printignore;

Frees temporarily allocated memory, prints an error message to the standard error and returns with the error code.

## 3. Error codes

Every igraph function which can fail return a single integer error code. Some functions are very simple and cannot run into any error, these may return other types, or void as well. The error codes are defined by the `igraph_error_type_t` enumeration.

### 3.1. `igraph_error_t` — Return type for functions returning an error code.

    typedef igraph_error_type_t igraph_error_t;

This type is used as the return type of igraph functions that return an error code. It is a type alias because igraph_error_t used to be an `int`, and was used slightly differenly than igraph_error_type_t.

### 3.2. `igraph_error_type_t` — Error code type.

    typedef enum {
        IGRAPH_SUCCESS           = 0,
        IGRAPH_FAILURE           = 1,
        IGRAPH_ENOMEM            = 2,
        IGRAPH_PARSEERROR        = 3,
        IGRAPH_EINVAL            = 4,
        IGRAPH_EXISTS            = 5,
        IGRAPH_EINVEVECTOR       = 6,
        IGRAPH_EINVVID           = 7,
        IGRAPH_NONSQUARE         = 8,
        IGRAPH_EINVMODE          = 9,
        IGRAPH_EFILE             = 10,
        IGRAPH_UNIMPLEMENTED     = 12,
        IGRAPH_INTERRUPTED       = 13,
        IGRAPH_DIVERGED          = 14,
        IGRAPH_ARPACK_PROD       = 15,   /* unused, reserved */
        IGRAPH_ARPACK_NPOS       = 16,
        IGRAPH_ARPACK_NEVNPOS    = 17,
        IGRAPH_ARPACK_NCVSMALL   = 18,
        IGRAPH_ARPACK_NONPOSI    = 19,
        IGRAPH_ARPACK_WHICHINV   = 20,
        IGRAPH_ARPACK_BMATINV    = 21,
        IGRAPH_ARPACK_WORKLSMALL = 22,
        IGRAPH_ARPACK_TRIDERR    = 23,
        IGRAPH_ARPACK_ZEROSTART  = 24,
        IGRAPH_ARPACK_MODEINV    = 25,
        IGRAPH_ARPACK_MODEBMAT   = 26,
        IGRAPH_ARPACK_ISHIFT     = 27,
        IGRAPH_ARPACK_NEVBE      = 28,
        IGRAPH_ARPACK_NOFACT     = 29,
        IGRAPH_ARPACK_FAILED     = 30,
        IGRAPH_ARPACK_HOWMNY     = 31,
        IGRAPH_ARPACK_HOWMNYS    = 32,
        IGRAPH_ARPACK_EVDIFF     = 33,
        IGRAPH_ARPACK_SHUR       = 34,
        IGRAPH_ARPACK_LAPACK     = 35,
        IGRAPH_ARPACK_UNKNOWN    = 36,
        IGRAPH_ENEGLOOP          = 37,
        IGRAPH_EINTERNAL         = 38,
        IGRAPH_ARPACK_MAXIT      = 39,
        IGRAPH_ARPACK_NOSHIFT    = 40,
        IGRAPH_ARPACK_REORDER    = 41,
        IGRAPH_EDIVZERO          = 42,
        IGRAPH_GLP_EBOUND        = 43,
        IGRAPH_GLP_EROOT         = 44,
        IGRAPH_GLP_ENOPFS        = 45,
        IGRAPH_GLP_ENODFS        = 46,
        IGRAPH_GLP_EFAIL         = 47,
        IGRAPH_GLP_EMIPGAP       = 48,
        IGRAPH_GLP_ETMLIM        = 49,
        IGRAPH_GLP_ESTOP         = 50,
        IGRAPH_EATTRIBUTES       = 51,
        IGRAPH_EATTRCOMBINE      = 52,
        IGRAPH_ELAPACK           = 53,
        IGRAPH_EDRL IGRAPH_DEPRECATED_ENUMVAL = 54,
        IGRAPH_EOVERFLOW         = 55,
        IGRAPH_EGLP              = 56,
        IGRAPH_CPUTIME           = 57,
        IGRAPH_EUNDERFLOW        = 58,
        IGRAPH_ERWSTUCK          = 59,
        IGRAPH_STOP              = 60,
        IGRAPH_ERANGE            = 61,
        IGRAPH_ENOSOL            = 62
    } igraph_error_type_t;

These are the possible values returned by igraph functions. Note that these are interesting only if you defined an error handler with `igraph_set_error_handler()`. Otherwise the program is aborted and the function causing the error never returns.

Values:

`IGRAPH_SUCCESS`: | The function successfully completed its task.
`IGRAPH_FAILURE`: | Something went wrong. You'll almost never meet this error as normally more specific error codes are used.
`IGRAPH_ENOMEM`: | There wasn't enough memory to allocate on the heap.
`IGRAPH_PARSEERROR`: | A parse error was found in a file.
`IGRAPH_EINVAL`: | A parameter's value is invalid. E.g. negative number was specified as the number of vertices.
`IGRAPH_EXISTS`: | A graph/vertex/edge attribute is already installed with the given name.
`IGRAPH_EINVEVECTOR`: | Invalid vector of vertex IDs. A vertex ID is either negative or bigger than the number of vertices minus one.
`IGRAPH_EINVVID`: | Invalid vertex ID, negative or too big.
`IGRAPH_NONSQUARE`: | A non-square matrix was received while a square matrix was expected.
`IGRAPH_EINVMODE`: | Invalid mode parameter.
`IGRAPH_EFILE`: | A file operation failed. E.g. a file doesn't exist, or the user has no rights to open it.
`IGRAPH_UNIMPLEMENTED`: | Attempted to call an unimplemented or disabled (at compile-time) function.
`IGRAPH_DIVERGED`: | A numeric algorithm failed to converge.
`IGRAPH_ARPACK_PROD`: | Matrix-vector product failed (not used any more).
`IGRAPH_ARPACK_NPOS`: | N must be positive.
`IGRAPH_ARPACK_NEVNPOS`: | NEV must be positive.
`IGRAPH_ARPACK_NCVSMALL`: | NCV must be bigger.
`IGRAPH_ARPACK_NONPOSI`: | Maximum number of iterations should be positive.
`IGRAPH_ARPACK_WHICHINV`: | Invalid WHICH parameter.
`IGRAPH_ARPACK_BMATINV`: | Invalid BMAT parameter.
`IGRAPH_ARPACK_WORKLSMALL`: | WORKL is too small.
`IGRAPH_ARPACK_TRIDERR`: | LAPACK error in tridiagonal eigenvalue calculation.
`IGRAPH_ARPACK_ZEROSTART`: | Starting vector is zero.
`IGRAPH_ARPACK_MODEINV`: | MODE is invalid.
`IGRAPH_ARPACK_MODEBMAT`: | MODE and BMAT are not compatible.
`IGRAPH_ARPACK_ISHIFT`: | ISHIFT must be 0 or 1.
`IGRAPH_ARPACK_NEVBE`: | NEV and WHICH='BE' are incompatible.
`IGRAPH_ARPACK_NOFACT`: | Could not build an Arnoldi factorization.
`IGRAPH_ARPACK_FAILED`: | No eigenvalues to sufficient accuracy.
`IGRAPH_ARPACK_HOWMNY`: | HOWMNY is invalid.
`IGRAPH_ARPACK_HOWMNYS`: | HOWMNY='S' is not implemented.
`IGRAPH_ARPACK_EVDIFF`: | Different number of converged Ritz values.
`IGRAPH_ARPACK_SHUR`: | Error from calculation of a real Schur form.
`IGRAPH_ARPACK_LAPACK`: | LAPACK (dtrevc) error for calculating eigenvectors.
`IGRAPH_ARPACK_UNKNOWN`: | Unknown ARPACK error.
`IGRAPH_ENEGLOOP`: | Negative loop detected while calculating shortest paths.
`IGRAPH_EINTERNAL`: | Internal error, likely a bug in igraph.
`IGRAPH_EDIVZERO`: | Big integer division by zero.
`IGRAPH_GLP_EBOUND`: | GLPK error (GLP_EBOUND).
`IGRAPH_GLP_EROOT`: | GLPK error (GLP_EROOT).
`IGRAPH_GLP_ENOPFS`: | GLPK error (GLP_ENOPFS).
`IGRAPH_GLP_ENODFS`: | GLPK error (GLP_ENODFS).
`IGRAPH_GLP_EFAIL`: | GLPK error (GLP_EFAIL).
`IGRAPH_GLP_EMIPGAP`: | GLPK error (GLP_EMIPGAP).
`IGRAPH_GLP_ETMLIM`: | GLPK error (GLP_ETMLIM).
`IGRAPH_GLP_ESTOP`: | GLPK error (GLP_ESTOP).
`IGRAPH_EATTRIBUTES`: | Attribute handler error. The user is not expected to find this; it is signalled if some igraph function is not using the attribute handler interface properly.
`IGRAPH_EATTRCOMBINE`: | Unimplemented attribute combination method for the given attribute type.
`IGRAPH_ELAPACK`: | A LAPACK call resulted in an error.
`IGRAPH_EDRL`: | Internal error in the DrL layout generator; not used any more (replaced by IGRAPH_EINTERNAL).
`IGRAPH_EOVERFLOW`: | Integer or double overflow.
`IGRAPH_EGLP`: | Internal GLPK error.
`IGRAPH_CPUTIME`: | CPU time exceeded.
`IGRAPH_EUNDERFLOW`: | Integer or double underflow.
`IGRAPH_ERWSTUCK`: | Random walk got stuck.
`IGRAPH_ERANGE`: | Maximum vertex or edge count exceeded.
`IGRAPH_ENOSOL`: | Input problem has no solution.

### 3.3. `igraph_strerror` — Textual description of an error.

     const char* igraph_strerror(const igraph_error_t igraph_errno);

This is a simple utility function, it gives a short general textual description for an igraph error code.

Arguments:

`igraph_errno`: | The igraph error code.

Returns:

`` | pointer to the textual description of the error code.

## 4. Warning messages

igraph also supports warning messages in addition to error messages. Warning messages typically do not terminate the program, but they are usually crucial to the user.

igraph warnings are handled similarly to errors. There is a separate warning handler function that is called whenever an igraph function triggers a warning. This handler can be set by the `igraph_set_warning_handler()` function. There are two predefined simple warning handlers, `igraph_warning_handler_ignore()` and `igraph_warning_handler_print()`, the latter being the default.

To trigger a warning, igraph functions typically use the `IGRAPH_WARNING()` macro, the `igraph_warning()` function, or if more flexibility is needed, `igraph_warningf()`.

### 4.1. `igraph_warning_handler_t` — The type of igraph warning handler functions.

    typedef void igraph_warning_handler_t (const char *reason, const char *file, int line);

Currently it is defined to have the same type as `igraph_error_handler_t`, although the last (error code) argument is not used.

### 4.2. `igraph_set_warning_handler` — Installs a warning handler.

     igraph_warning_handler_t* igraph_set_warning_handler(igraph_warning_handler_t* new_handler);

Install the supplied warning handler function.

Arguments:

`new_handler`: | The new warning handler function to install. Supply a null pointer here to uninstall the current warning handler, without installing a new one.

Returns:

`` | The current warning handler function.

### 4.3. `IGRAPH_WARNING` — Triggers a warning.

    #define IGRAPH_WARNING(reason)

This is the usual way of triggering a warning from an igraph function. It calls `igraph_warning()`.

Arguments:

`reason`: | The warning message.

### 4.4. `IGRAPH_WARNINGF` — Triggers a warning, with printf-like syntax.

    #define IGRAPH_WARNINGF

igraph functions can use this macro when they notice a warning and want to pass on extra information to the user about what went wrong. It calls `igraph_warningf()` with the proper parameters and no error code.

Arguments:

`reason`: | Textual description of the warning, a template string with the same syntax as the standard printf C library function.
`...`: | The additional arguments to be substituted into the template string.

### 4.5. `igraph_warning` — Reports a warning.

     void igraph_warning(const char *reason, const char *file, int line);

Call this function if you want to trigger a warning from within a function that uses igraph.

Arguments:

`reason`: | Textual description of the warning.
`file`: | The source file in which the warning was noticed.
`line`: | The number of line in the source file which triggered the warning.
`igraph_errno`: | Warnings could have potentially error codes as well, but this is currently not used in igraph.

Returns:

`` | The supplied error code.

### 4.6. `igraph_warningf` — Reports a warning, printf-like version.

    IGRAPH_FUNCATTR_PRINTFLIKE(1,4)
    IGRAPH_EXPORT void igraph_warningf(const char *reason, const char *file, int line, ...);

This function is similar to `igraph_warning()`, but uses a printf-like syntax. It substitutes the additional arguments into the `reason` template string and calls `igraph_warning()`.

Arguments:

`reason`: | Textual description of the warning, a template string with the same syntax as the standard printf C library function.
`file`: | The source file in which the warning was noticed.
`line`: | The number of line in the source file which triggered the warning.
`igraph_errno`: | Warnings could have potentially error codes as well, but this is currently not used in igraph.
`...`: | The additional arguments to be substituted into the template string.

### 4.7. `igraph_warning_handler_ignore` — Ignores all warnings.

    void igraph_warning_handler_ignore(const char *reason, const char *file, int line);

This warning handler function simply ignores all warnings.

Arguments:

`reason`: | Textual description of the warning.
`file`: | The source file in which the warning was noticed.
`line`: | The number of line in the source file which triggered the warning..
`igraph_errno`: | Warnings could have potentially error codes as well, but this is currently not used in igraph.

### 4.8. `igraph_warning_handler_print` — Prints all warnings to the standard error.

    void igraph_warning_handler_print(const char *reason, const char *file, int line);

This warning handler function simply prints all warnings to the standard error.

Arguments:

`reason`: | Textual description of the warning.
`file`: | The source file in which the warning was noticed.
`line`: | The number of line in the source file which triggered the warning..
`igraph_errno`: | Warnings could have potentially error codes as well, but this is currently not used in igraph.

## 5. Advanced topics

### 5.1. Writing error handlers

The contents of the rest of this chapter might be useful only for those who want to create an interface to igraph from another language, or use igraph from a GUI application. Most readers can safely skip to the next chapter.

You can write and install error handlers simply by defining a function of type `igraph_error_handler_t` and calling `igraph_set_error_handler()`. This feature is useful for interface writers, as igraph will have the chance to signal errors the appropriate way. For example, the R interface uses R's native printing facilities to communicate errors, while the Python interface converts them into Python exceptions.

The two main tasks of the error handler are to report the error (i.e. print the error message) and ensure proper resource cleanup. This is ensured by calling `IGRAPH_FINALLY_FREE()`, which deallocates some of the temporary memory to avoid memory leaks. Note that this may invalidate the error message buffer `reason` passed to the error handler. Do not access it after having called `IGRAPH_FINALLY_FREE()`.

As of igraph 0.10, temporary memory is dellocated in stages, through multiple calls to the error handler (and indirectly to `IGRAPH_FINALLY_FREE()`). Therefore, error handlers that do not abort the program immediately are expected to return. The error handler should not perform a `longjmp`, as this may lead to some of the memory not getting freed.

#### 5.1.1. `igraph_set_error_handler` — Sets a new error handler.

     igraph_error_handler_t* igraph_set_error_handler(igraph_error_handler_t* new_handler);

Installs a new error handler. If called with `NULL`, it installs the default error handler (which is currently `igraph_error_handler_abort`).

Arguments:

`new_handler`: | The error handler function to install.

Returns:

`` | The old error handler function. This should be saved and restored if `new_handler` is not needed any more.

### 5.2. Error handling internals

If an error happens, the functions in the library call the `IGRAPH_ERROR()` macro with a textual description of the error and an igraph error code. This macro calls (through the `igraph_error()` function) the installed error handler. Another useful macro is `IGRAPH_CHECK()`. This checks the return value of its argument, which is normally a function call, and calls `IGRAPH_ERROR()` if it is not `IGRAPH_SUCCESS`.

#### 5.2.1. `IGRAPH_ERROR` — Triggers an error.

    #define IGRAPH_ERROR(reason, igraph_errno)

igraph functions usually use this macro when they notice an error. It calls `igraph_error()` with the proper parameters and if that returns the macro returns the "calling" function as well, with the error code. If for some (suspicious) reason you want to call the error handler without returning from the current function, call `igraph_error()` directly.

Arguments:

`reason`: | Textual description of the error. This should be something more descriptive than the text associated with the error code. E.g. if the error code is `IGRAPH_EINVAL`, its associated text (see `igraph_strerror()`) is "Invalid value" and this string should explain which parameter was invalid and maybe why.
`igraph_errno`: | The igraph error code.

#### 5.2.2. `IGRAPH_ERRORF` — Triggers an error, with printf-like syntax.

    #define IGRAPH_ERRORF

igraph functions can use this macro when they notice an error and want to pass on extra information to the user about what went wrong. It calls `igraph_errorf()` with the proper parameters and if that returns the macro returns the "calling" function as well, with the error code. If for some (suspicious) reason you want to call the error handler without returning from the current function, call `igraph_errorf()` directly.

Arguments:

`reason`:

Textual description of the error, a template string with the same syntax as the standard printf C library function. This should be something more descriptive than the text associated with the error code. E.g. if the error code is `IGRAPH_EINVAL`, its associated text (see `igraph_strerror()`) is "Invalid value" and this string should explain which parameter was invalid and maybe what was expected and what was recieved.

`igraph_errno`: | The igraph error code.
`...`: | The additional arguments to be substituted into the template string.

#### 5.2.3. `igraph_error` — Reports an error.

     igraph_error_t igraph_error(const char *reason, const char *file, int line,
                                   igraph_error_t igraph_errno);

igraph functions usually call this function (most often via the `IGRAPH_ERROR` macro) if they notice an error. It calls the currently installed error handler function with the supplied arguments.

Arguments:

`reason`: | Textual description of the error.
`file`: | The source file in which the error was noticed.
`line`: | The number of line in the source file which triggered the error.
`igraph_errno`: | The igraph error code.

Returns:

`` | the error code (if it returns)

See also:

`` | igraph_errorf().

#### 5.2.4. `igraph_errorf` — Reports an error, printf-like version.

    IGRAPH_FUNCATTR_PRINTFLIKE(1,5)
    IGRAPH_EXPORT igraph_error_t igraph_errorf(const char *reason, const char *file, int line,
                                    igraph_error_t igraph_errno, ...);

Arguments:

`reason`: | Textual description of the error, interpreted as a `printf` format string.
`file`: | The source file in which the error was noticed.
`line`: | The line in the source file which triggered the error.
`igraph_errno`: | The igraph error code.
`...`: | Additional parameters, the values to substitute into the format string.

See also:

`` | igraph_error().

#### 5.2.5. `IGRAPH_CHECK` — Checks the return value of a function call.

    #define IGRAPH_CHECK(expr)

Arguments:

`expr`: | An expression, usually a function call. It is guaranteed to be evaluated only once.

Executes the expression and checks its value. If this is not `IGRAPH_SUCCESS`, it calls `IGRAPH_ERROR` with the value as the error code. Here is an example usage:

     IGRAPH_CHECK(vector_push_back(&v, 100));

There is only one reason to use this macro when writing igraph functions. If the user installs an error handler which returns to the auxiliary calling code (like `igraph_error_handler_ignore` and `igraph_error_handler_printignore`), and the igraph function signalling the error is called from another igraph function then we need to make sure that the error is propagated back to the auxiliary (i.e. non-igraph) calling function. This is achieved by using `IGRAPH_CHECK` on every igraph call which can return an error code.

#### 5.2.6. `IGRAPH_CHECK_CALLBACK` — Checks the return value of a callback.

    #define IGRAPH_CHECK_CALLBACK(expr, code)

Identical to `IGRAPH_CHECK`, but treats `IGRAPH_STOP` as a normal (non-erroneous) return code. This macro is used in some igraph functions that allow the user to hook into a long-running calculation with a callback function. When the user-defined callback function returns `IGRAPH_SUCCESS`, the calculation will proceed normally. Returning `IGRAPH_STOP` from the callback will terminate the calculation without reporting an error. Returning any other value from the callback is treated as an error code, and igraph will trigger the necessary cleanup functions before exiting the function.

Note that `IGRAPH_CHECK_CALLBACK` does not handle `IGRAPH_STOP` by any means except returning it in the variable pointed to by `code`. It is the responsibility of the caller to handle `IGRAPH_STOP` accordingly.

Arguments:

`expr`: | An expression, usually a call to a user-defined callback function. It is guaranteed to be evaluated only once.
`code`: | Pointer to an optional variable of type igraph_error_t; the value of this variable will be set to the error code if it is not a null pointer.

### 5.3. Deallocating memory

If a function runs into an error (and the program is not aborted) the error handler should deallocate all temporary memory. This is done by storing the address and the destroy function of all temporary objects in a stack. The `IGRAPH_FINALLY` function declares an object as temporary by placing its address in the stack. If an igraph function returns with success it calls `IGRAPH_FINALLY_CLEAN()` with the number of objects to remove from the stack. If an error happens however, the error handler should call `IGRAPH_FINALLY_FREE()` to deallocate each object added to the stack. This means that the temporary objects allocated in the calling function (and etc.) will be freed as well.

#### 5.3.1. `IGRAPH_FINALLY` — Registers an object for deallocation.

    #define IGRAPH_FINALLY(func, ptr)

This macro places the address of an object, together with the address of its destructor in a stack. This stack is used if an error happens to deallocate temporarily allocated objects to prevent memory leaks. After manual deallocation, objects are removed from the stack using `IGRAPH_FINALLY_CLEAN()`.

Arguments:

`func`: | The function which is normally called to destroy the object.
`ptr`: | Pointer to the object itself.

#### 5.3.2. `IGRAPH_FINALLY_CLEAN` — Signals clean deallocation of objects.

     void IGRAPH_FINALLY_CLEAN(int num);

Removes the specified number of objects from the stack of temporarily allocated objects. It is typically called immediately after manually destroying the objects:

    igraph_vector_t vector;
    igraph_vector_init(&vector, 10);
    IGRAPH_FINALLY(igraph_vector_destroy, &vector);
    // use vector
    igraph_vector_destroy(&vector);
    IGRAPH_FINALLY_CLEAN(1);

Arguments:

`num`: | The number of objects to remove from the bookkeeping stack.

#### 5.3.3. `IGRAPH_FINALLY_FREE` — Deallocates objects registered at the current level.

     void IGRAPH_FINALLY_FREE(void);

Calls the destroy function for all objects in the current level of the stack of temporarily allocated objects, i.e. up to the nearest mark set by `IGRAPH_FINALLY_ENTER()`. This function must only be called from an error handler. It is not appropriate to use it instead of destroying each unneeded object of a function, as it destroys the temporary objects of the caller function (and so on) as well.

### 5.4. Writing igraph functions with proper error handling

There are some simple rules to keep in order to have functions behaving well in erroneous situations. First, check the arguments of the functions and call `IGRAPH_ERROR()` if they are invalid. Second, call `IGRAPH_FINALLY` on each dynamically allocated object and call `IGRAPH_FINALLY_CLEAN()` with the proper argument before returning. Third, use `IGRAPH_CHECK` on all igraph function calls which can generate errors.

The size of the stack used for this bookkeeping is fixed, and small. If you want to allocate several objects, write a destroy function which can deallocate all of these. See the `adjlist.c` file in the igraph source for an example.

For some functions these mechanisms are simply not flexible enough. These functions should define their own error handlers and restore the error handler before they return.

### 5.5. Fatal errors

In some rare situations, igraph may encounter an internal error that cannot be fully handled. In this case, it will call the current fatal error handler. The default fatal error handler simply prints the error and aborts the program.

Fatal error handlers do not return. Typically, they might abort the the program immediately, or in the case of the high-level igraph interfaces, they might return to the top level using a `longjmp()`. The fatal error handler is only called when a serious error has occurred, and as a result igraph may be in an inconsistent state. The purpose of returning to the top level is to give the user a chance to save their work instead of aborting immediately. However, the program session should be restarted as soon as possible.

Most projects that use igraph will use the default fatal error handler.

#### 5.5.1. `igraph_fatal_handler_t` — The type of igraph fatal error handler functions.

    typedef void igraph_fatal_handler_t (const char *reason, const char *file, int line);

Functions of this type must not return. Typically they call `abort()` or do a `longjmp()`.

Arguments:

`reason`: | Textual description of the error.
`file`: | The source file in which the error is noticed.
`line`: | The number of the line in the source file which triggered the error.

#### 5.5.2. `igraph_set_fatal_handler` — Installs a fatal error handler.

     igraph_fatal_handler_t* igraph_set_fatal_handler(igraph_fatal_handler_t* new_handler);

Installs the supplied fatal error handler function.

Fatal error handler functions must not return. Typically, the fatal error handler would either call `abort()` or `longjmp()`.

Arguments:

`new_handler`: | The new fatal error handler function to install. Supply a null pointer here to uninstall the current fatal error handler, without installing a new one.

Returns:

`` | The current fatal error handler function.

#### 5.5.3. `igraph_fatal_handler_abort` — Abort program in case of fatal error.

    IGRAPH_EXPORT igraph_fatal_handler_t igraph_fatal_handler_abort;

The default fatal error handler, prints an error message and aborts the program.

#### 5.5.4. `IGRAPH_FATAL` — Triggers a fatal error.

    #define IGRAPH_FATAL(reason)

This is the usual way of triggering a fatal error from an igraph function. It calls `igraph_fatal()`.

Use this macro only in situations where the error cannot be handled. The normal way to handle errors is `IGRAPH_ERROR()`.

Arguments:

`reason`: | The error message.

#### 5.5.5. `IGRAPH_FATALF` — Triggers a fatal error, with printf-like syntax.

    #define IGRAPH_FATALF

igraph functions can use this macro when a fatal error occurs and want to pass on extra information to the user about what went wrong. It calls `igraph_fatalf()` with the proper parameters.

Arguments:

`reason`: | Textual description of the error, a template string with the same syntax as the standard printf C library function.
`...`: | The additional arguments to be substituted into the template string.

#### 5.5.6. `IGRAPH_ASSERT` — igraph-specific replacement for `assert()`.

    #define IGRAPH_ASSERT(condition)

This macro is like the standard `assert()`, but instead of calling `abort()`, it calls `igraph_fatal()`. This allows for returning the control to the calling program, e.g. returning to the top level in a high-level igraph interface.

Unlike `assert()`, `IGRAPH_ASSERT()` is not disabled when the `NDEBUG` macro is defined.

This macro is meant for internal use by igraph.

Since a typical fatal error handler does a `longjmp()`, avoid using this macro in C++ code. With most compilers, destructor will not be called when `longjmp()` leaves the current scope.

Arguments:

`condition`: | The condition to be checked.

#### 5.5.7. `igraph_fatal` — Triggers a fatal error.

     IGRAPH_FUNCATTR_NORETURN void igraph_fatal(const char *reason, const char *file, int line);

This function triggers a fatal error. Typically it is called indirectly through `IGRAPH_FATAL()` or `IGRAPH_ASSERT()`.

Arguments:

`reason`: | Textual description of the error.
`file`: | The source file in which the error was noticed.
`line`: | The number of line in the source file which triggered the error.

#### 5.5.8. `igraph_fatalf` — Triggers a fatal error, printf-like syntax.

    IGRAPH_FUNCATTR_PRINTFLIKE(1,4)
    IGRAPH_EXPORT IGRAPH_FUNCATTR_NORETURN void igraph_fatalf(const char *reason, const char *file, int line, ...);

This function is similar to `igraph_fatal()`, but uses a printf-like syntax. It substitutes the additional arguments into the `reason` template string and calls `igraph_fatal()`.

Arguments:

`reason`: | Textual description of the error.
`file`: | The source file in which the error was noticed.
`line`: | The number of line in the source file which triggered the error.
`...`: | The additional arguments to be substituted into the template string.

### 5.6. Error handling and threads

It is likely that the igraph error handling method is not thread-safe, mainly because of the static global stack which is used to store the address of the temporarily allocated objects. This issue might be addressed in a later version of igraph.