nautechsystems/nautilus_trader · error · anyhow::Error
Failed to initialize tracing subscriber: {e}
Error message
Failed to initialize tracing subscriber: {e} What it means
`init_tracing` builds a fmt tracing subscriber with the Nautilus formatter and installs it via `tracing::subscriber::set_global_default`. The global default subscriber can only be set once per process, so a second initialization attempt returns this error wrapping the tracing SetGlobalDefaultError.
Source
Thrown at crates/common/src/logging/bridge.rs:113
/// # Errors
///
/// Returns an error if the tracing subscriber has already been initialized.
pub fn init_tracing() -> anyhow::Result<()> {
if TRACING_INITIALIZED.load(Ordering::SeqCst) {
anyhow::bail!("Tracing subscriber already initialized");
}
let filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("warn"));
let subscriber = tracing_subscriber::registry()
.with(filter)
.with(fmt::layer().event_format(NautilusFormatter));
// Install only the tracing subscriber here. Python logging manages the
// global `log` logger separately, so we must not claim it through
// SubscriberInitExt::try_init().
tracing::subscriber::set_global_default(subscriber)
.map_err(|e| anyhow::anyhow!("Failed to initialize tracing subscriber: {e}"))?;
TRACING_INITIALIZED.store(true, Ordering::SeqCst);
Ok(())
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use super::*;
#[rstest]
fn test_tracing_is_initialized_returns_bool() {
let _ = tracing_is_initialized();
}
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Call init_tracing only once per process; gate it behind a OnceLock/once flag or the library's existing TRACING_INITIALIZED check.
- Check the returned error's source for 'a global default trace dispatcher has already been set' to detect double init.
- Use tracing::subscriber::with_default (thread-local) or set_default in scoped contexts instead of global installation for tests.
- Ensure the host application does not install its own global subscriber before nautilus init.
Example fix
// before
init_tracing(level)?; // called in setup and again in each test
// after
static INIT: OnceLock<()> = OnceLock::new();
if INIT.set(()).is_ok() {
init_tracing(level)?;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Rust: guard against double global subscriber install
static TRACING_DONE: OnceLock<()> = OnceLock::new();
if TRACING_DONE.get().is_some() { return Ok(()); } Type guard
fn tracing_ready() -> bool { TRACING_INITIALIZED.load(Ordering::SeqCst) } Try / catch
if let Err(e) = init_tracing(level) {
if e.to_string().contains("already been set") { debug!("tracing already installed"); }
else { return Err(e); }
} Prevention
- Install the global subscriber exactly once at process entry.
- Use thread-local with_default for tests needing isolated subscribers.
- Coordinate init between host application and library (single init entry point).
- Gate init behind OnceLock/atomic flags even in test harnesses.
When it happens
Trigger: Calling init_tracing (or a higher-level init that reaches it) more than once in the same process — e.g. a test harness and the code under test both calling it, multiple subsystems initializing logging, or re-running after a previous call already flipped TRACING_INITIALIZED.
Common situations: Running multiple tests in one process that each call init; embedding nautilus into an app that already installed its own tracing subscriber; double-start of a runtime/node; mixing init_tracing with another crate that claims the global subscriber.
Related errors
- Tracing subscriber already initialized
- Command receiver already taken
- Invalid spec pair: {kv}
- Logging has been shut down and cannot be re-initialized
- Global logging sender was already published
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/9d8f75e83ad827cc.
Report an issue: GitHub.