vectordotdev/vector · error
Failed type coercion, {self:?} is not a Stream
Error message
Failed type coercion, {self:?} is not a Stream What it means
into_stream() is the inverse coercion on VectorSink: it unwraps the Stream variant (a boxed StreamSink<EventArray>) and panics if the value is the Sink variant. Like into_sink(), the panic is documented and indicates the caller assumed the wrong sink shape at runtime.
Source
Thrown at lib/vector-core/src/sink.rs:61
/// # Panics
///
/// This function will panic if the self instance is not `VectorSink::Sink`.
pub fn into_sink(self) -> Box<dyn Sink<EventArray, Error = ()> + Send + Unpin> {
match self {
Self::Sink(sink) => sink,
_ => panic!("Failed type coercion, {self:?} is not a Sink"),
}
}
/// Converts `VectorSink` into a `StreamSink`
///
/// # Panics
///
/// This function will panic if the self instance is not `VectorSink::Stream`.
pub fn into_stream(self) -> Box<dyn StreamSink<EventArray> + Send> {
match self {
Self::Stream(stream) => stream,
_ => panic!("Failed type coercion, {self:?} is not a Stream"),
}
}
/// Converts an event sink into a `VectorSink`
///
/// Deprecated in favor of `VectorSink::from_event_streamsink`. See [vector/9261]
/// for more info.
///
/// [vector/9261]: https://github.com/vectordotdev/vector/issues/9261
#[deprecated]
pub fn from_event_sink(sink: impl Sink<Event, Error = ()> + Send + Unpin + 'static) -> Self {
VectorSink::Sink(Box::new(EventSink::new(sink)))
}
/// Converts an event stream into a `VectorSink`
pub fn from_event_streamsink(sink: impl StreamSink<Event> + Send + 'static) -> Self {
let sink = Box::new(sink);
VectorSink::Stream(Box::new(EventStream { sink }))View on GitHub (pinned to 3708c39b12)
Solutions
- Branch on the variant: use into_stream() only for VectorSink::Stream, into_sink() for VectorSink::Sink
- Prefer VectorSink::run(input) so the enum is consumed without assuming either shape
- If a StreamSink is required downstream, wrap the futures::Sink with an adapter that implements StreamSink instead of coercing
Example fix
// before
let stream_sink = vector_sink.into_stream(); // panics for Sink variant
// after
if matches!(vector_sink, VectorSink::Stream(_)) {
let stream_sink = vector_sink.into_stream();
} else {
let fut_sink = vector_sink.into_sink();
} Defensive patterns
Strategy: type-guard
Validate before calling
if matches!(vector_sink, VectorSink::Stream(_)) {
let s = vector_sink.into_stream(); // safe
} else {
let s = vector_sink.into_sink();
} Type guard
fn is_stream_variant(v: &VectorSink) -> bool {
matches!(v, VectorSink::Stream(_))
} Prevention
- Consume sinks through VectorSink::run unless you specifically need one shape
- When a StreamSink is required, adapt futures::Sink implementations instead of coercing
- Check the variant in debug_assertions to catch shape mismatches in tests
When it happens
Trigger: Calling sink.into_stream() on a VectorSink built as VectorSink::Sink (e.g. via from_event_sink or a sink adapter wrapping a futures::Sink), usually in stream-driving wrapper code.
Common situations: Wrapper code written for the StreamSink model receiving a legacy or custom sink that wraps futures::Sink; test harnesses that consume every sink as a stream.
Related errors
- Failed type coercion, {self:?} is not a Sink
- path and query should never fail to parse
- Failed type coercion, {self:?} is not a log event
- Failed type coercion, {self:?} is not a metric
- Failed type coercion, {self:?} is not a log reference
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/b3447693011461c2.
Report an issue: GitHub.