linera-io/linera-protocol · error

test-log: RUST_LOG_SPAN_EVENTS must be valid UTF-8

Error message

test-log: RUST_LOG_SPAN_EVENTS must be valid UTF-8

What it means

linera-storage-service configures tracing-subscriber span events from the RUST_LOG_SPAN_EVENTS variable (filters: new, enter, exit, close, active, full). It reads the variable with std::env::var_os, which returns an OsString because Unix environment variables are arbitrary bytes, then calls .to_str(); that returns None when the bytes are not valid UTF-8, and .expect() panics before the server starts. The 'test-log:' prefix comes from the well-known tokio test-log snippet this code follows.

Source

Thrown at linera-storage-service/src/server.rs:611

    )]
    async fn process_delete_all(&self, _request: Request<()>) -> Result<Response<()>, Status> {
        self.delete_all().await?;
        Ok(Response::new(()))
    }
}

#[tokio::main]
async fn main() {
    let env_filter = tracing_subscriber::EnvFilter::builder()
        .with_default_directive(tracing_subscriber::filter::LevelFilter::INFO.into())
        .from_env_lossy();
    let internal_event_filter = {
        match std::env::var_os("RUST_LOG_SPAN_EVENTS") {
            Some(mut value) => {
                value.make_ascii_lowercase();
                let value = value
                    .to_str()
                    .expect("test-log: RUST_LOG_SPAN_EVENTS must be valid UTF-8");
                value
                    .split(',')
                    .map(|filter| match filter.trim() {
                        "new" => FmtSpan::NEW,
                        "enter" => FmtSpan::ENTER,
                        "exit" => FmtSpan::EXIT,
                        "close" => FmtSpan::CLOSE,
                        "active" => FmtSpan::ACTIVE,
                        "full" => FmtSpan::FULL,
                        _ => panic!("test-log: RUST_LOG_SPAN_EVENTS must contain filters separated by `,`.\n\t\
                                     For example: `active` or `new,close`\n\t\
                                     Supported filters: new, enter, exit, close, active, full\n\t\
                                     Got: {value}"),
                    })
                    .fold(FmtSpan::NONE, |acc, filter| filter | acc)
            }
            None => FmtSpan::NONE,
        }

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Re-set the variable to plain ASCII filters: export RUST_LOG_SPAN_EVENTS="new,close"
  2. Or unset it entirely: None selects FmtSpan::NONE and the server starts normally
  3. Find the offending bytes with `printf '%s' "$RUST_LOG_SPAN_EVENTS" | od -c` and look for non-ASCII byte sequences
  4. Re-save the script/.env/CI variable definition as UTF-8

Example fix

# before: .env saved as latin-1, RUST_LOG_SPAN_EVENTS="café,close" carries 0xE9 bytes -> panic
# after: UTF-8 file, or ASCII-only value
export RUST_LOG_SPAN_EVENTS="new,close"
Defensive patterns

Strategy: validation

Validate before calling

// Rust launcher: use var() (UTF-8 checked) instead of var_os before spawning the server
match std::env::var("RUST_LOG_SPAN_EVENTS") {
    Ok(v) => { /* safe: guaranteed valid UTF-8 */ }
    Err(std::env::VarError::NotUnicode(_)) => { /* clear the variable or abort with a clear message */ }
    Err(std::env::VarError::NotPresent) => {}
}

Prevention

When it happens

Trigger: Starting linera-storage-service with RUST_LOG_SPAN_EVENTS whose raw bytes are non-UTF-8: a latin-1 encoded accented character, a stray 0x80-0xFF byte, or a value injected from a script or .env file saved in a legacy encoding. Pure-ASCII values like `new,close` never trigger it.

Common situations: Values written by older Windows shells or PowerShell in a legacy code page; .env files saved by a non-UTF-8 editor; CI variables pasted from rich text with invisible non-UTF-8 bytes; Docker ENV injected from a binary file.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/276f0e8969662e4d. Report an issue: GitHub.