valeriansaliou/sonic · error · panic

invalid log level

Error message

invalid log level

What it means

In main(), the startup log level is read from the SONIC_SERVER__LOG_LEVEL environment variable and parsed with LevelFilter::from_str; an unrecognized value panics with "invalid log level" before the server even starts. The value must be a valid log crate level name.

Source

Thrown at server/src/main.rs:98

        .about(clap::crate_description!())
        .arg(
            Arg::new("config")
                .short('c')
                .long("config")
                .help("Path to configuration file"),
        )
        .get_matches();

    // Generate owned app arguments
    AppArgs {
        config: matches.get_one::<String>("config").cloned(),
    }
}

fn main() {
    ConfigLogger::init(
        std::env::var("SONIC_SERVER__LOG_LEVEL")
            .map(|level| LevelFilter::from_str(&level).expect("invalid log level"))
            .unwrap_or(LevelFilter::DEBUG),
    );

    let app_args = make_app_args();

    let app_conf = read_config(app_args.config.as_deref());

    ConfigLogger::update(
        LevelFilter::from_str(&app_conf.server.log_level).expect("invalid log level"),
    );

    // Validate the app configuration.
    {
        let invalid_stopwords = (app_conf.sonic.stopwords.allow)
            .intersection(&app_conf.sonic.stopwords.deny)
            .collect::<Vec<_>>();
        if !invalid_stopwords.is_empty() {
            tracing::error!(invalid = ?invalid_stopwords, "Some stopwords are both allowed and denied. Fix your `stopwords` configuration.");

View on GitHub (pinned to e6a72da6a5)

Solutions

  1. Set SONIC_SERVER__LOG_LEVEL to one of: off, error, warn, info, debug, trace
  2. Trim whitespace and remove enclosing quotes from the env value
  3. Unset the variable to fall back to the default DEBUG level
  4. Note: after config load the log_level config field is parsed the same way — make both consistent

Example fix

// before
export SONIC_SERVER__LOG_LEVEL=verbose
// after
export SONIC_SERVER__LOG_LEVEL=debug
Defensive patterns

Strategy: validation

Validate before calling

// Rust/shell: validate before launch
LEVEL="${SONIC_SERVER__LOG_LEVEL:-debug}"
case "${LEVEL,,}" in off|error|warn|info|debug|trace) ;; *) echo "invalid log level: $LEVEL"; exit 1;; esac

Type guard

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

Try / catch

let level = LevelFilter::from_str(&raw).unwrap_or(LevelFilter::DEBUG); // or log + exit instead of expect

Prevention

When it happens

Trigger: Setting SONIC_SERVER__LOG_LEVEL to anything other than off/error/warn/info/debug/trace (case variations like DEBUG are accepted by from_str; arbitrary words or numbers are not).

Common situations: Typos in env var value ("verbose", "5"); copy-pasted values with surrounding whitespace/quotes; CI or Kubernetes manifests exporting an invalid default.

Related errors


AI-assisted analysis of valeriansaliou/sonic@e6a72da6a5 (2026-09-01). Data as JSON: /api/errors/cf8980b93dca4ad7. Report an issue: GitHub.