influxdata/influxdb · error · Error

Cannot set global tracing subscriber

Error message

Cannot set global tracing subscriber

What it means

This is a variant of trogging's `Error` enum wrapping `tracing::dispatcher::SetGlobalDefaultError`. It occurs when initializing logging fails because a global tracing subscriber was already set (the global default can only be set once per process). The library converts the underlying tracing error into this user-readable message via `#[from]`.

Solutions

  1. Initialize the global subscriber exactly once, early in main.
  2. Guard with `tracing::dispatcher::has_been_set()` or ignore the second init attempt.
  3. In tests, use a local default subscriber (tracing::subscriber::with_default) instead of the global one.

Example fix

// before
let _ = trogging::Builder::new().build().unwrap().init();
init_logging_again(); // panics: already set
// after
if !tracing::dispatcher::has_been_set() {
    let _ = trogging::Builder::new().build().unwrap().init();
}
Defensive patterns

Strategy: try-catch

Validate before calling

if tracing::dispatcher::has_been_set() {
    eprintln!("global subscriber already set; skipping init");
}

Type guard

fn can_init_global_tracing() -> bool {
    !tracing::dispatcher::has_been_set()
}

Try / catch

match trogging::Builder::new().build().init() {
    Ok(_) => {}
    Err(trogging::Error::SetGlobalDefaultError(_)) => { /* already initialized */ }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: Calling trogging's builder init (e.g. `Builder::new()...build().init()` or `set_global_default`) after another component already installed a global tracing subscriber in the same process.

Common situations: A binary initializes logging twice (e.g. main() plus a library's init); running tests where each test tries to set a global subscriber; embedding the server in another app that has its own tracing setup.

Related errors


AI-assisted analysis of influxdata/influxdb@06200ef96b (2026-09-19). Data as JSON: /api/errors/171c01e7e7aa5eaf. Report an issue: GitHub.

Appendix: source

Thrown at core/trogging/src/lib.rs:37

    EnvFilter, Layer,
    fmt::{self, MakeWriter, writer::BoxMakeWriter},
    layer::SubscriberExt,
    registry::LookupSpan,
};

/// Maximum length of a log line.
/// Space for a final trailing newline if truncated.
///
/// Docker "chunks" log message in 16KB chunks. The log driver receives log lines in such chunks
/// but not all of the log drivers properly recombine the lines, and even those who do have their
/// own max buffer sizes (e.g. for our fluentd config it's 32KB).
/// To avoid surprises, for now, let's just truncate log lines right below 16K and make sure
/// they are properly terminated with a newline if they were so before the truncation.
const MAX_LINE_LENGTH: usize = 16 * 1024 - 1;

#[derive(Debug, Error)]
pub enum Error {
    #[error("Cannot set global tracing subscriber")]
    SetGlobalDefaultError(#[from] tracing::dispatcher::SetGlobalDefaultError),

    #[error("Cannot set global log subscriber")]
    SetLoggerError(#[from] tracing_log::log_tracer::SetLoggerError),

    #[error("`tokio_console` feature not enabled")]
    TokioConsoleMissing,
}

pub type Result<T, E = Error> = std::result::Result<T, E>;

/// Builder to configure tracing and logging.
#[derive(Debug)]
pub struct Builder<W = fn() -> io::Stdout> {
    log_format: LogFormat,
    log_filter: Option<EnvFilter>,
    // used when log_filter is none.
    default_log_filter: EnvFilter,

View on GitHub (pinned to 06200ef96b)