vectordotdev/vector · error

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

Error message

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

What it means

`Event::as_metric` (lib/vector-core/src/event/mod.rs:172-181) borrows the event as `&Metric` and panics with a debug dump when the event is `Event::Log` or `Event::Trace`. Metric-oriented components (aggregations, metric sinks) rely on this precondition; code that cannot guarantee the variant must check first, since no fallible borrow twin exists for metrics in this impl.

Source

Thrown at lib/vector-core/src/event/mod.rs:180

    /// Return self as a `LogEvent` if possible
    ///
    /// If the event is a `LogEvent`, then `Some(&log_event)` is returned, otherwise `None`.
    pub fn maybe_as_log(&self) -> Option<&LogEvent> {
        match self {
            Event::Log(log) => Some(log),
            _ => None,
        }
    }

    /// Return self as a `Metric`
    ///
    /// # Panics
    ///
    /// This function panics if self is anything other than an `Event::Metric`.
    pub fn as_metric(&self) -> &Metric {
        match self {
            Event::Metric(metric) => metric,
            _ => panic!("Failed type coercion, {self:?} is not a metric"),
        }
    }

    /// Return self as a mutable `Metric`
    ///
    /// # Panics
    ///
    /// This function panics if self is anything other than an `Event::Metric`.
    pub fn as_mut_metric(&mut self) -> &mut Metric {
        match self {
            Event::Metric(metric) => metric,
            _ => panic!("Failed type coercion, {self:?} is not a metric"),
        }
    }

    /// Coerces self into `Metric`
    ///
    /// # Panics

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Guard with `matches!(event, Event::Metric(_))` before calling `as_metric`.
  2. Branch on the variant and route non-metric events to their proper handler or drop them with an emitted error.
  3. Split the topology so metrics sources and log sources feed separate pipelines.

Example fix

// before
let metric = event.as_metric(); // panics on Log/Trace

// after
match &event {
    Event::Metric(metric) => aggregate(metric),
    other => emit!(UnexpectedEvent { event: &other }),
}
Defensive patterns

Strategy: type-guard

Validate before calling

if matches!(event, Event::Metric(_)) {
    let metric = event.as_metric();
}

Type guard

fn is_metric_event(e: &Event) -> bool { matches!(e, Event::Metric(_)) }

Prevention

When it happens

Trigger: Calling `event.as_metric()` on a log event, e.g. a metrics aggregation transform or a Prometheus-style sink receiving logs because sources and sinks were wired into the same stream; trace events from an OTLP source hitting the same call.

Common situations: A pipeline where `stdin`/file/http log sources share a topology branch with a metrics sink; custom metric transforms reusing generic event loops; fixtures that build log events but exercise metric-only code paths.

Related errors


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