nautechsystems/nautilus_trader · error · anyhow::Error
Tracing subscriber already initialized
Error message
Tracing subscriber already initialized
What it means
init_tracing installs the process-global tracing subscriber exactly once, guarded by the TRACING_INITIALIZED atomic flag. If the subscriber has already been initialized (flag set), calling init_tracing again returns this error rather than re-installing or silently no-oping, because a global subscriber can only be set once per process.
Source
Thrown at crates/common/src/logging/bridge.rs:100
/// Initializes a tracing subscriber for external Rust crate logging.
///
/// This sets up a standard tracing subscriber that outputs to stdout with
/// the format controlled by `RUST_LOG` environment variable. The output
/// format uses nanosecond timestamps to align with Nautilus logging.
///
/// # Environment Variables
///
/// - `RUST_LOG`: Controls which modules emit tracing events and at what level.
/// - Example: `RUST_LOG=hyper=debug,tokio=warn`.
/// - Default: `warn` (if not set).
///
/// # 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(())
}
View on GitHub (pinned to 18893faf8b)
Solutions
- Call init_tracing only once at process startup; propagate the Result and skip on this specific error if double-init is expected.
- In tests, use a OnceGuard/OnceCell or an integration-test harness so only one test (or a shared once-guard) initializes tracing.
- If the host application already set a subscriber, remove the library-side init call instead of calling init_tracing.
Example fix
// before
setup()?; // calls init_tracing every time
init_tracing()?;
// after
static INIT: Once = Once::new();
INIT.call_once(|| {
if let Err(e) = init_tracing() {
eprintln!("tracing init skipped: {e}");
}
}); Defensive patterns
Strategy: try-catch
Try / catch
// rust
match init_tracing() {
Ok(()) => tracing::info!("tracing initialized"),
Err(e) if e.to_string() == "Tracing subscriber already initialized" => {
// expected in tests / multi-bootstrap: safe to ignore
}
Err(e) => return Err(e.into()),
} Prevention
- Initialize tracing exactly once in process main, not inside libraries or per-test helpers.
- Wrap init in std::sync::Once or a OnceLock so repeated calls are impossible.
- In test suites, use a shared harness guarded by Once instead of calling init_tracing per test.
- If embedding in an app with its own subscriber, make library tracing init opt-in via config.
When it happens
Trigger: Calling init_tracing twice in the same process — e.g. once in a library/runner bootstrap and again in application main; re-running initialization in tests that share a process; restarting a subsystem that calls init as part of its setup.
Common situations: Test binaries where each #[test] calls a common setup helper that calls init_tracing; embedding the library in an app that already configured its own tracing subscriber; retry logic that re-invokes initialization after an unrelated failure.
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
- Failed to initialize tracing subscriber: {e}
- 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/bba2b17ad5655279.
Report an issue: GitHub.