vectordotdev/vector · error

stream must exist in the event

Error message

stream must exist in the event

What it means

The Legacy branch of line_agg_adapter reads the stdout/stderr tag with log.get(event_path!(STREAM)).expect("stream must exist in the event"). docker_logs inserted the stream field when decoding each line, so this is again an internal invariant; the panic fires when an event reaches multiline aggregation without that field.

Source

Thrown at src/sources/docker_logs/mod.rs:1356

        let message_value = match log_namespace {
            LogNamespace::Vector => log
                .remove(&vrl::path::OwnedTargetPath::event_root())
                .expect("`.` must exist in the event"),
            LogNamespace::Legacy => log
                .remove(
                    log_schema()
                        .message_key_target_path()
                        .expect("global log_schema.message_key to be valid path"),
                )
                .expect("`message` must exist in the event"),
        };
        let stream_value = match log_namespace {
            LogNamespace::Vector => log
                .get(metadata_path!(DockerLogsConfig::NAME, STREAM))
                .expect("`docker_logs.stream` must exist in the metadata"),
            LogNamespace::Legacy => log
                .get(event_path!(STREAM))
                .expect("stream must exist in the event"),
        };

        let stream = stream_value.coerce_to_bytes();
        let message = message_value.coerce_to_bytes();
        (stream, message, log)
    });
    let line_agg_out = LineAgg::<_, Bytes, LogEvent>::new(line_agg_in, logic);
    line_agg_out.map(move |(_, message, mut log, _)| {
        match log_namespace {
            LogNamespace::Vector => log.insert(&vrl::path::OwnedTargetPath::event_root(), message),
            LogNamespace::Legacy => log.insert(
                log_schema()
                    .message_key_target_path()
                    .expect("global log_schema.message_key to be valid path"),
                message,
            ),
        };
        log

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Check with a console sink that events still contain the stream field under this config
  2. Remove custom stages between source and aggregator
  3. Patch: default the stream to empty bytes with a warning instead of expecting
  4. Report upstream and upgrade

Example fix

// before
LogNamespace::Legacy => log
    .get(event_path!(STREAM))
    .expect("stream must exist in the event"),

// after
LogNamespace::Legacy => log
    .get(event_path!(STREAM))
    .unwrap_or_else(|| {
        warn!(message = "event missing stream field before line_agg");
        Value::Bytes(Bytes::new())
    }),
Defensive patterns

Strategy: validation

Validate before calling

let stream_value = log
    .get(event_path!(STREAM))
    .cloned()
    .unwrap_or_else(|| {
        warn!(message = "missing stream field");
        Value::Bytes(Bytes::new())
    });

Type guard

fn has_stream_field(log: &LogEvent) -> bool {
    log.get(event_path!(STREAM)).is_some()
}

Try / catch

let stream = log
    .remove(event_path!(STREAM))
    .map(|v| v.coerce_to_bytes())
    .unwrap_or_else(|| { warn!("missing stream"); Bytes::new() });

Prevention

When it happens

Trigger: An event skipping or losing the stream insertion stage - a regression or custom code path between line decode and line_agg - while multiline is enabled in Legacy namespace.

Common situations: Version upgrades touching docker_logs event shaping; forks with extra processing stages before aggregation.

Related errors


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