vectordotdev/vector · error

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

Error message

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

What it means

`EventRef<'a>` is a borrowed, clone-free view over an `Event` (Log/Metric/Trace reference variants) used to avoid allocations on hot paths. `EventRef::as_log` (lib/vector-core/src/event/ref.rs:26-32) unwraps only the `Log` variant and panics with a debug dump otherwise, per its `# Panics` doc. `into_log` on the same type additionally clones the borrowed log event.

Source

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

pub enum EventRef<'a> {
    /// Reference to a `LogEvent`
    Log(&'a LogEvent),
    /// Reference to a `Metric`
    Metric(&'a Metric),
    /// Reference to a `TraceEvent`
    Trace(&'a TraceEvent),
}

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

    /// Convert this reference into a new `LogEvent` by cloning.
    ///
    /// # 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

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Match on the `EventRef` variant and only call `as_log` in the `Self::Log` arm.
  2. Skip or emit an internal error event for non-log variants instead of coercing.
  3. Keep log-only consumers on a routed branch that only ever emits log events.

Example fix

// before
let log = event_ref.as_log(); // panics for Metric/Trace refs

// after
match event_ref {
    EventRef::Log(log) => forward(log),
    EventRef::Metric(_) | EventRef::Trace(_) => emit!(WrongSignalType),
}
Defensive patterns

Strategy: type-guard

Validate before calling

if let EventRef::Log(_) = event_ref {
    let log = event_ref.as_log();
}

Type guard

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

Prevention

When it happens

Trigger: Calling `event_ref.as_log()` (or `event_ref.into_log()`) on an `EventRef::Metric`/`EventRef::Trace` — e.g. fan-out code that iterates pipeline outputs as `EventRef`s and forwards each to a log-only consumer such as a log sink acknowledgement or serializer path.

Common situations: Custom sinks or middleware consuming `Vec<EventRef>` from a topology output where metrics/traces share the stream; refactoring owned-`Event` code (which used `try_into_log`) to the zero-copy `EventRef` API and dropping the variant check in the process.

Related errors


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