stalwartlabs/stalwart · error

Invalid LOG level

Error message

Invalid LOG level

What it means

This panic comes from `Level::from_str(&level).expect("Invalid LOG level")` during telemetry/tracer setup in `parse`. The `LOG` environment variable is read only when the `dev_mode` feature is enabled, and it must parse into a trc `Level` via `Level::from_str`. That parser (crates/trc/src/event/level.rs:44) only accepts the case-insensitive strings "disable", "trace", "debug", "info", "warn", and "error"; anything else makes `from_str` return `Err` and the `expect` panics with "Invalid LOG level", aborting configuration parsing.

Source

Thrown at crates/common/src/config/telemetry.rs:530

                // Parse webhook events
                apply_events(hook.events, hook.events_policy, |event_type| {
                    if event_type != EventType::Telemetry(TelemetryEvent::WebhookError) {
                        tracer.interests.set(event_type);
                        global_interests.set(event_type);
                    }
                });

                if !tracer.interests.is_empty() {
                    tracers.push(tracer);
                } else {
                    bp.build_error(id, "No events enabled for webhook");
                }
            }

            #[cfg(feature = "dev_mode")]
            if let Ok(level) = std::env::var("LOG") {
                let level = Level::from_str(&level).expect("Invalid LOG level");
                for event_type in EventType::variants() {
                    let event_level = custom_levels
                        .get(event_type)
                        .copied()
                        .unwrap_or(event_type.level());
                    if level.is_contained(event_level) {
                        global_interests.set(event_type.to_id() as usize);
                    }
                }

                tracers.push(TelemetrySubscriber {
                    id: "default".to_string(),
                    interests: global_interests.clone(),
                    typ: TelemetrySubscriberType::ConsoleTracer(ConsoleTracer {
                        ansi: true,
                        multiline: false,
                        buffered: true,
                    }),

View on GitHub (pinned to e962003857)

Solutions

  1. Set LOG to one of the exact accepted values (case-insensitive): disable, trace, debug, info, warn, or error — e.g. LOG=debug.
  2. Remove RUST_LOG-style per-module filters; a single level token is the only accepted form.
  3. Trim whitespace from the value: export LOG="$(echo "$LOG" | tr -d '[:space:]')" or fix the Dockerfile/systemd unit/export that introduces it.
  4. If you meant per-event granularity, use the config's event log level settings (custom_levels) instead of the LOG env var.
  5. If you are not intentionally running a dev_mode build, unset LOG entirely — the var is only read when the dev_mode feature is compiled in.

Example fix

// before
LOG=warning stalwart-mailserver   # panics: Invalid LOG level

// after
LOG=warn stalwart-mailserver
Defensive patterns

Strategy: validation

Validate before calling

const VALID_LEVELS: [&str; 6] = ["disable", "trace", "debug", "info", "warn", "error"];
let log = std::env::var("LOG").unwrap_or_default();
assert!(VALID_LEVELS.contains(&log.to_ascii_lowercase().as_str()), "LOG must be one of {:?}, got {:?}", VALID_LEVELS, log);

Type guard

fn is_valid_log_level(s: &str) -> bool {
    matches!(s.to_ascii_lowercase().as_str(), "disable" | "trace" | "debug" | "info" | "warn" | "error")
}

Prevention

When it happens

Trigger: Setting the LOG env var (with the binary built with the dev_mode feature) to anything outside {disable, trace, debug, info, warn, error} — e.g. LOG=verbose, LOG=5, LOG=warning, LOG=trace,debug (a comma-separated RUST_LOG-style filter is NOT accepted), or a value with surrounding whitespace/newline.

Common situations: Developers copying RUST_LOG-style syntax ("info,foo=debug") from other Rust projects; typing "warning" or "critical" instead of "warn"/"error"; numeric log levels; exporting LOG="info " with a trailing space in a shell profile or Docker ENV; running a dev_mode build in an environment where LOG was set for an unrelated tool.

Understand the failure class

Background: "is not a valid" / "Invalid ... value" environment variable errors: how libraries validate env vars and what to do when they reject yours — this error's family across 48 libraries.

Related errors


AI-assisted analysis of stalwartlabs/stalwart@e962003857 (2026-09-06). Data as JSON: /api/errors/ddeed222449cb40c. Report an issue: GitHub.