vectordotdev/vector · error

Failed type coercion, {self:?} is not a metric reference

Error message

Failed type coercion, {self:?} is not a metric reference

What it means

EventRef::as_metric() extracts the &'a Metric from an EventRef, panicking unless the reference is the Metric variant. The panic is an invariant assertion: the API is designed for call sites that have already established the event is a metric, so any other variant reaching this code is a logic bug in the caller.

Source

Thrown at lib/vector-core/src/event/ref.rs:52

    /// # Panics
    ///
    /// This will panic if this is not a `LogEvent` reference.
    pub fn into_log(self) -> LogEvent {
        match self {
            Self::Log(log) => log.clone(),
            _ => panic!("Failed type coercion, {self:?} is not a log reference"),
        }
    }

    /// Extract the `Metric` reference in this.
    ///
    /// # Panics
    ///
    /// This will panic if this is not a `Metric` reference.
    pub fn as_metric(self) -> &'a Metric {
        match self {
            Self::Metric(metric) => metric,
            _ => panic!("Failed type coercion, {self:?} is not a metric reference"),
        }
    }

    /// Convert this reference into a new `Metric` by cloning.
    ///
    /// # Panics
    ///
    /// This will panic if this is not a `Metric` reference.
    pub fn into_metric(self) -> Metric {
        match self {
            Self::Metric(metric) => metric.clone(),
            _ => panic!("Failed type coercion, {self:?} is not a metric reference"),
        }
    }
}

impl<'a> From<&'a Event> for EventRef<'a> {
    fn from(event: &'a Event) -> Self {

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Narrow first: only call as_metric() when matches!(event_ref, EventRef::Metric(_))
  2. Branch on the source Event with match event { Event::Metric(m) => ..., _ => ... } so the compiler guarantees the type
  3. Fix the pipeline wiring so metric-only code only receives metrics (inputs/outputs declarations)

Example fix

// before
let metric = event_ref.as_metric(); // panics if not Metric

// after
if let EventRef::Metric(_) = event_ref {
    let metric = event_ref.as_metric();
    // ...
}
Defensive patterns

Strategy: type-guard

Validate before calling

if let EventRef::Metric(_) = event_ref {
    let metric = event_ref.as_metric(); // safe
}

Type guard

fn is_metric_ref(r: &EventRef<'_>) -> bool {
    matches!(r, EventRef::Metric(_))
}

Prevention

When it happens

Trigger: Calling event_ref.as_metric() when the EventRef wraps a LogEvent or TraceEvent, e.g. metric-accumulator code fed from a logs source, or a match that falls through to a blanket coercion branch.

Common situations: Custom metric transforms or sinks connected to log inputs; code that inspects Event::as_log()/as_metric() based on a stale or wrong discriminant check; unit tests using mixed event fixtures where a log slips into the metric path.

Related errors


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