vectordotdev/vector · error

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

Error message

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

What it means

`Event` is an enum over `Log`, `Metric` and `Trace`, and `Event::as_log` (lib/vector-core/src/event/mod.rs:119-125) is the infallible-looking borrow conversion that only works on `Event::Log`. Any other variant panics with a debug dump of the event. The `# Panics` doc states the precondition; the fallible twin `try_into_log` exists for code that cannot guarantee the variant.

Source

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

    fn get_tags(&self) -> TaggedEventsSent {
        match self {
            Event::Log(log) => log.get_tags(),
            Event::Metric(metric) => metric.get_tags(),
            Event::Trace(trace) => trace.get_tags(),
        }
    }
}

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

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

    /// Coerces self into a `LogEvent`
    ///
    /// # Panics

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Match on the variant or use the fallible API: `event.try_into_log()`, handling `None` by skipping or erroring that event.
  2. Fix the topology: add a `filter`/`route` transform (or correct source/sink wiring) so only log events reach components that call `as_log`.
  3. If writing a component, declare its accepted input types in the component traits so the topology validates it at config-load time.

Example fix

// before
let log = event.as_log(); // panics on Event::Metric/Event::Trace

// after
match event {
    Event::Log(log) => handle_log(&log),
    Event::Metric(m) => handle_metric(&m),
    Event::Trace(t) => handle_trace(&t),
}
// or fallibly: let Some(log) = event.try_into_log() else { return Ok(()) };
Defensive patterns

Strategy: type-guard

Validate before calling

if matches!(event, Event::Log(_)) {
    let log = event.as_log();
    // safe: guarded
}

Type guard

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

Prevention

When it happens

Trigger: Calling `event.as_log()` on an event produced by a metrics source (`host_metrics`, `prometheus_scrape`, `internal_metrics`) or a trace source (`opentelemetry`), e.g. a log-oriented transform or sink written against `&LogEvent` that receives `Event::Metric`/`Event::Trace` from the topology.

Common situations: Adding a metrics source to a pipeline whose sinks/transforms assume logs (e.g. routing `internal_metrics` into a log-only transform); custom components that call `as_log` on every incoming event without checking; multiplexed pipelines where a route transform is missing so mixed event types reach log consumers.

Related errors


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