nautechsystems/nautilus_trader · error · anyhow::Error

Logging has been shut down and cannot be re-initialized

Error message

Logging has been shut down and cannot be re-initialized

What it means

The global logger tracks its lifecycle (Uninitialized, Running, Terminated). Once logging has been explicitly shut down (Terminated), calling init again is refused with this error because re-initialization after teardown is not supported. The logger must remain in its terminated state for the process lifetime after shutdown.

Source

Thrown at crates/common/src/logging/logger.rs:927

    )]
    pub fn init_with_config(
        trader_id: TraderId,
        instance_id: UUID4,
        config: LoggerConfig,
        file_config: FileWriterConfig,
    ) -> anyhow::Result<LogGuard> {
        let mut lifecycle = LOGGER_LIFECYCLE.lock();

        match *lifecycle {
            LoggerLifecycle::Running => {
                return LogGuard::new_locked().ok_or_else(|| {
                    anyhow::anyhow!(
                        "Logging already initialized but new guard could not be created"
                    )
                });
            }
            LoggerLifecycle::Terminated => {
                anyhow::bail!("Logging has been shut down and cannot be re-initialized");
            }
            LoggerLifecycle::Uninitialized => {}
        }

        let (tx, rx) = std::sync::mpsc::channel::<LogEvent>();
        let filter_policy = FilterPolicy::from_config(&config);

        #[cfg(not(all(feature = "simulation", madsim)))]
        let handle = std::thread::Builder::new()
            .name(LOGGING.to_string())
            .spawn({
                let config = config.clone();
                let file_config = file_config.clone();
                move || {
                    Self::handle_messages(
                        trader_id.to_string(),
                        instance_id.to_string(),
                        config,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Restructure the application to initialize logging exactly once, at startup, and never call shutdown until process exit.
  2. If shutdown was called in a test, run it in a separate process or use a test harness that does not share the global logger.
  3. Check that no early-exit/error path calls shutdown before the intended re-init.
  4. If reconfiguration is needed, rebuild the config and re-init only while lifecycle is Uninitialized/Running per the API, not after Terminated.

Example fix

// before
logging_shutdown();
logging_init(new_config)?; // bails: Terminated
// after
logging_init(new_config)?; // init once at startup
// ... run ...
logging_shutdown(); // only at process exit
Defensive patterns

Strategy: try-catch

Validate before calling

fn can_init_logging(shutdown_called: std::cell::Cell<bool>) -> bool { !shutdown_called.get() }

Try / catch

match logging_init(cfg) {
    Err(e) if e.to_string().contains("shut down and cannot be re-initialized") => {
        // logging permanently stopped; proceed without logging or fail fast
        eprintln!("logging unavailable: {e}");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling the logging init function (e.g. logger::init / logging initialization entry point) after a previous init was shut down via the logger's shutdown/flush-and-terminate path.

Common situations: Test harnesses that initialize logging per test after a global shutdown ran, application code that stops and restarts logging on config reload, or embedded usage where logging is torn down between sessions.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/f52f854fca08fc77. Report an issue: GitHub.