quickwit-oss/quickwit · error

{QW_METRICS_LABELS_ENV_VAR} must contain valid Unicode

Error message

{QW_METRICS_LABELS_ENV_VAR} must contain valid Unicode

What it means

init_metrics_labels_env_var reads QW_METRICS_LABELS_ENV_VAR directly from the environment (to avoid a circular dependency on quickwit-common) and bails if its value is not valid Unicode. Quickwit cannot attach the configured metric labels without a decodable value.

Source

Thrown at quickwit/quickwit-metrics/src/lib.rs:407

        (c.info.key_name, buckets)
    })
}

/// Initializes the global metrics labels from the environment variable.
pub fn init_metrics_labels_env_var() -> anyhow::Result<()> {
    // If the labels environment variable is already initialized, return early.
    if LABELS_ENV_VAR.get().is_some() {
        return Ok(());
    }

    // quickwit-common defines common helpers for getting environment variables.
    // However, we need to use the `std::env::var` function directly here because
    // quickwit-common depends on quickwit-metrics and it would cause a circular dependency.
    let labels = match std::env::var(QW_METRICS_LABELS_ENV_VAR) {
        Ok(labels) => labels,
        Err(std::env::VarError::NotPresent) => String::new(),
        Err(std::env::VarError::NotUnicode(_)) => {
            anyhow::bail!("{QW_METRICS_LABELS_ENV_VAR} must contain valid Unicode")
        }
    };
    let parsed_labels = parse_metrics_labels(&labels)?;
    LABELS_ENV_VAR.get_or_init(|| parsed_labels.into_boxed_slice());

    Ok(())
}

// The format of the environment variable is:
// QW_METRICS_LABELS="environment=test,region=us-east-1,foo=bar"
fn parse_metrics_labels(labels: &str) -> anyhow::Result<Vec<Label>> {
    let mut parsed_labels: Vec<Label> = Vec::new();
    if labels.trim().is_empty() {
        return Ok(parsed_labels);
    }

    const LABELS_SEPARATOR: char = ',';
    const KEY_VALUE_SEPARATOR: char = '=';

View on GitHub (pinned to a39730c5cd)

Solutions

  1. Re-set the variable with valid UTF-8, e.g. export QW_METRICS_LABELS_ENV_VAR="cluster=prod"
  2. Check the source of the value with `env | grep QW_METRICS` and re-encode it (e.g. iconv)
  3. Remove the variable entirely to fall back to the empty default

Example fix

// before
export QW_METRICS_LABELS_ENV_VAR=$'cluster=pr\xffod'
// after
export QW_METRICS_LABELS_ENV_VAR="cluster=prod"
Defensive patterns

Strategy: validation

Validate before calling

if let Ok(v) = std::env::var("QW_METRICS_LABELS_ENV_VAR") {
    if std::str::from_utf8(v.as_bytes()).is_err() { eprintln!("value is not valid UTF-8"); }
}

Try / catch

if let Err(e) = init_metrics_labels_env_var() {
    if e.to_string().contains("valid Unicode") {
        eprintln!("fix QW_METRICS_LABELS_ENV_VAR encoding: {e}");
        std::process::exit(1);
    }
}

Prevention

When it happens

Trigger: Starting Quickwit with QW_METRICS_LABELS_ENV_VAR set to bytes that are not valid UTF-8 (e.g. raw binary or a non-UTF-8 locale-encoded value in the environment).

Common situations: Exporting the env var from a script with mis-encoded bytes; setting it via a container runtime that injects raw values; shell locale issues.

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 quickwit-oss/quickwit@a39730c5cd (2026-09-08). Data as JSON: /api/errors/ab7941be163050b9. Report an issue: GitHub.