# How to Implement a Custom Error Handler in spdlog

> Implement a custom error handler in spdlog by setting a callback function. Learn how to intercept spdlog internal failures with set_error_handler for global or individual logger error management.

- Repository: [Gabi Melman/spdlog](https://github.com/gabime/spdlog)
- Tags: how-to-guide
- Published: 2026-07-21

---

**You can intercept spdlog internal failures by calling `spdlog::set_error_handler()` with a callback function that receives `const std::string&`, or by using `logger::set_error_handler()` for individual logger instances.**

The gabime/spdlog library provides a robust mechanism to capture and process internal logging errors—such as file permission failures or sink write errors—through customizable error handlers. When you implement a custom error handler in spdlog, you gain control over how the library reports failures, allowing you to redirect errors to monitoring systems, throw exceptions, or execute recovery logic instead of the default `stderr` output.

## Understanding the Error Handler Architecture

spdlog operates with two distinct scopes for error handling: **global** and **per-logger**. The global error handler serves as the default fallback for all loggers, while individual loggers can override this behavior with specialized handlers.

When an internal error occurs, spdlog invokes the registered handler with a descriptive message. The handler signature must conform to `void(const std::string& msg)`. According to the source code in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h) (line 91), the global API is declared as:

```cpp
void set_error_handler(void(*handler)(const std::string& msg));

```

The implementation in [`include/spdlog/spdlog-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog-inl.h) (line 54) delegates to the registry, which stores the handler and propagates it to newly created loggers via [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h) (line 79) and its inline implementation in [`registry-inl.h`](https://github.com/gabime/spdlog/blob/main/registry-inl.h) (lines 165-168).

## Setting a Global Error Handler

To establish a default error handling strategy across your entire application, install a global handler before creating any loggers. This approach ensures that every logger created subsequently inherits the custom error processing logic unless explicitly overridden.

The global handler is particularly useful for centralized error monitoring or when you need uniform failure reporting across multiple loggers. As implemented in [`include/spdlog/spdlog-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog-inl.h), the function stores your callback in the internal registry, making it available to all future logger instances.

Here is how to define and register a global error handler:

```cpp
#include <spdlog/spdlog.h>
#include <iostream>

void my_global_handler(const std::string& msg)
{
    // Redirect to monitoring system or alternative logging
    std::cerr << "[CRITICAL LOG ERROR] " << msg << std::endl;
    
    // Optionally terminate or throw based on severity
    // std::terminate();
}

int main()
{
    // Install before creating any loggers
    spdlog::set_error_handler(my_global_handler);
    
    // This logger inherits the global handler
    auto console = spdlog::stdout_color_mt("console");
}

```

## Implementing Per-Logger Error Handlers

For scenarios requiring differentiated error handling strategies, spdlog allows you to override the global handler on individual logger instances. The `logger` class declares this capability in [`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h) (line 310):

```cpp
void set_error_handler(err_handler handler);

```

The implementation resides in [`include/spdlog/logger-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger-inl.h) (line 112), where the member function replaces the logger's internal error handler pointer. This design enables file-specific error recovery, network sink isolation, or distinct alerting thresholds per logging channel.

Per-logger handlers take precedence over the global handler, allowing fine-grained control:

```cpp
auto file_logger = spdlog::basic_logger_mt("file", "/read-only/path/app.log");

// Override with lambda handler for this specific logger
file_logger->set_error_handler([](const std::string& msg)
{
    std::cerr << "[File Logger Specific] Failed to write: " << msg << std::endl;
    // Implement file-specific recovery or alerting
});

```

## Complete Implementation Example

The following example demonstrates both global and per-logger error handler installation, showcasing how to implement a custom error handler in spdlog for comprehensive failure management:

```cpp
// custom_error_handling.cpp
#include <spdlog/spdlog.h>
#include <iostream>
#include <stdexcept>

void global_error_handler(const std::string& msg)
{
    std::cerr << "[Global Handler] spdlog error: " << msg << std::endl;
    // Could integrate with external monitoring here
}

int main()
{
    // 1. Set global handler before any logger creation
    spdlog::set_error_handler(global_error_handler);
    
    // 2. Create console logger (inherits global handler)
    auto console = spdlog::stdout_color_mt("console");
    console->info("Console logger initialized");
    
    // 3. Create file logger with specific error handling
    auto file_logger = spdlog::basic_logger_mt("file", "logs.txt");
    file_logger->set_error_handler([](const std::string& msg)
    {
        // Custom behavior for file operations
        std::cerr << "[File Handler] Disk write failed: " << msg << std::endl;
        throw std::runtime_error("Logging infrastructure failure: " + msg);
    });
    
    // 4. Operations that trigger error handling
    file_logger->error("This invokes the per-logger handler on failure");
    
    return 0;
}

```

## Summary

- **Global Installation**: Use `spdlog::set_error_handler()` defined in [`include/spdlog/spdlog.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog.h) to establish a default error callback for all loggers, implemented in [`include/spdlog/spdlog-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog-inl.h).
- **Per-Logger Override**: Call `set_error_handler()` on individual logger instances (declared in [`include/spdlog/logger.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger.h), implemented in [`include/spdlog/logger-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger-inl.h)) to implement logger-specific error processing.
- **Handler Signature**: All error handlers must conform to `void(const std::string& msg)` and receive descriptive failure messages from the library.
- **Registry Propagation**: The global handler propagates through [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h) to new loggers via the mechanism in [`registry-inl.h`](https://github.com/gabime/spdlog/blob/main/registry-inl.h) (lines 165-168).

## Frequently Asked Questions

### What signature must a custom spdlog error handler implement?

Your custom error handler must implement the function signature `void(const std::string& msg)`. The library passes a descriptive error message string when internal failures occur, such as file permission denials or sink write failures. This applies to both global handlers set via `spdlog::set_error_handler()` and per-logger handlers set via `logger::set_error_handler()`.

### How do I make a specific logger use a different error handler than the global default?

Call `set_error_handler()` directly on the logger instance after creation. According to the implementation in [`include/spdlog/logger-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/logger-inl.h) (line 112), this method overrides the global handler stored in the registry. The per-logger handler takes exclusive precedence for that specific logger instance, while other loggers continue using the global handler.

### Can I throw exceptions from within a spdlog error handler?

Yes, you can throw exceptions from your error handler implementation, but be aware that this will propagate out from the logging call site. Since spdlog error handlers are called when the library encounters internal failures (like being unable to write to a sink), throwing exceptions here may interrupt your application's normal logging flow. Ensure your surrounding code is prepared to catch these exceptions if you choose this approach.

### Where does spdlog store the global error handler internally?

The global error handler is stored in the internal registry class defined in [`include/spdlog/details/registry.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/details/registry.h) (line 79). When you call `spdlog::set_error_handler()`, the implementation in [`include/spdlog/spdlog-inl.h`](https://github.com/gabime/spdlog/blob/main/include/spdlog/spdlog-inl.h) (line 54) forwards the callback to this registry. Newly created loggers receive this handler during initialization through the propagation logic in [`registry-inl.h`](https://github.com/gabime/spdlog/blob/main/registry-inl.h) (lines 165-168), unless explicitly overridden per-logger.