vectordotdev/vector · error

argument must be a string

Error message

argument must be a string

What it means

The aggregate_vector_metrics VRL function's helper does key.as_str().expect("argument must be a string") (lib/vector-vrl/metrics/src/aggregate_vector_metrics.rs). The function declares its key parameter as required BYTES, so the VRL compiler guarantees a bytes value at the call site; the expect is a defensive invariant asserting that guarantee held at runtime.

Source

Thrown at lib/vector-vrl/metrics/src/aggregate_vector_metrics.rs:52

                },
            ]),
        Parameter::required("key", kind::BYTES, "The metric name to aggregate."),
        Parameter::optional(
            "tags",
            kind::OBJECT,
            "Tags to filter the results on. Values in this object support wildcards ('*') to match on parts of the tag value.",
        )
        .default(&DEFAULT_TAGS),
    ]
});

fn aggregate_metrics(
    metrics_storage: &MetricsStorage,
    function: &Bytes,
    key: Value,
    tags: BTreeMap<String, String>,
) -> Result<Value, ExpressionError> {
    let key_str = key.as_str().expect("argument must be a string");
    let metrics = metrics_storage.find_metrics(&key_str, tags);

    let metric_values = metrics.into_iter().filter_map(|m| match m.value() {
        vector_core::event::MetricValue::Counter { value }
        | vector_core::event::MetricValue::Gauge { value } => NotNan::new(*value).ok(),
        _ => None,
    });

    Ok(match function.as_ref() {
        b"sum" => metric_values.sum::<NotNan<f64>>().into(),
        b"avg" => {
            let len = metric_values.clone().collect::<Vec<_>>().len();
            (metric_values.sum::<NotNan<f64>>() / len as f64).into()
        }
        b"max" => metric_values.max().map(Into::into).unwrap_or(Value::Null),
        b"min" => metric_values.min().map(Into::into).unwrap_or(Value::Null),
        _ => unreachable!(),
    })

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Keep all vector-vrl crates on one release in your dependency tree
  2. Call it with literal metric names or to_string!-coerced values: aggregate_vector_metrics("component_received", ...)
  3. Embed VRL through the compiled Program API so kind enforcement runs first
  4. Report stock-build reproducers upstream

Example fix

# before (vrl)
aggregate_vector_metrics(key)   # key: any

# after (vrl)
aggregate_vector_metrics(to_string!(key))
Defensive patterns

Strategy: type-guard

Validate before calling

# Pass a literal metric name or coerce to string
aggregate_vector_metrics(to_string!(key))

Type guard

fn is_bytes(v: &vrl::value::Value) -> bool {
    matches!(v, vrl::value::Value::Bytes(_))
}

Prevention

When it happens

Trigger: Executing aggregate_vector_metrics with a key that is not bytes/string at runtime — blocked at compile time in normal use (aggregate_vector_metrics(1, ...) fails to compile); reachable only via compiler bugs, mismatched vector-vrl crate versions, or direct helper invocation in embeddings/tests.

Common situations: Custom VRL embeds that skip compilation; development of the VRL type checker; workspace dependency skew between vector-vrl-metrics and the compiler crates.

Related errors


AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20). Data as JSON: /api/errors/d44937a053ebb342. Report an issue: GitHub.