{"record":{"id":"d44937a053ebb342","repo":"vectordotdev/vector","slug":"argument-must-be-a-string-d44937","errorCode":null,"errorMessage":"argument must be a string","messagePattern":"argument must be a string","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/vector-vrl/metrics/src/aggregate_vector_metrics.rs","lineNumber":52,"sourceCode":"                },\n            ]),\n        Parameter::required(\"key\", kind::BYTES, \"The metric name to aggregate.\"),\n        Parameter::optional(\n            \"tags\",\n            kind::OBJECT,\n            \"Tags to filter the results on. Values in this object support wildcards ('*') to match on parts of the tag value.\",\n        )\n        .default(&DEFAULT_TAGS),\n    ]\n});\n\nfn aggregate_metrics(\n    metrics_storage: &MetricsStorage,\n    function: &Bytes,\n    key: Value,\n    tags: BTreeMap<String, String>,\n) -> Result<Value, ExpressionError> {\n    let key_str = key.as_str().expect(\"argument must be a string\");\n    let metrics = metrics_storage.find_metrics(&key_str, tags);\n\n    let metric_values = metrics.into_iter().filter_map(|m| match m.value() {\n        vector_core::event::MetricValue::Counter { value }\n        | vector_core::event::MetricValue::Gauge { value } => NotNan::new(*value).ok(),\n        _ => None,\n    });\n\n    Ok(match function.as_ref() {\n        b\"sum\" => metric_values.sum::<NotNan<f64>>().into(),\n        b\"avg\" => {\n            let len = metric_values.clone().collect::<Vec<_>>().len();\n            (metric_values.sum::<NotNan<f64>>() / len as f64).into()\n        }\n        b\"max\" => metric_values.max().map(Into::into).unwrap_or(Value::Null),\n        b\"min\" => metric_values.min().map(Into::into).unwrap_or(Value::Null),\n        _ => unreachable!(),\n    })","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/lib/vector-vrl/metrics/src/aggregate_vector_metrics.rs#L34-L70","documentation":"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.","triggerScenarios":"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.","commonSituations":"Custom VRL embeds that skip compilation; development of the VRL type checker; workspace dependency skew between vector-vrl-metrics and the compiler crates.","solutions":["Keep all vector-vrl crates on one release in your dependency tree","Call it with literal metric names or to_string!-coerced values: aggregate_vector_metrics(\"component_received\", ...)","Embed VRL through the compiled Program API so kind enforcement runs first","Report stock-build reproducers upstream"],"exampleFix":"# before (vrl)\naggregate_vector_metrics(key)   # key: any\n\n# after (vrl)\naggregate_vector_metrics(to_string!(key))","handlingStrategy":"type-guard","validationCode":"# Pass a literal metric name or coerce to string\naggregate_vector_metrics(to_string!(key))","typeGuard":"fn is_bytes(v: &vrl::value::Value) -> bool {\n    matches!(v, vrl::value::Value::Bytes(_))\n}","tryCatchPattern":null,"preventionTips":["Quote metric names as literals in VRL","Validate configs with vector validate before deploy","Embed through the compiled Program handle only"],"tags":["vector","vrl","metrics","type-invariant","panic","internal"],"backgroundTag":"type-invariant-violation","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}