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,
),
};
logView on GitHub (pinned to 3708c39b12)
Solutions
- Check with a console sink that events still contain the stream field under this config
- Remove custom stages between source and aggregator
- Patch: default the stream to empty bytes with a warning instead of expecting
- 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
- Keep the field name (STREAM) defined once and used by both insert and read sites
- Integration-test Legacy namespace with multiline aggregation
- Log-and-default instead of expect for optional grouping fields
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
- `.` must exist in the event
- `message` must exist in the event
- `docker_logs.stream` must exist in the metadata
- Every ContainerLogInfo has it's ContainerState
- Every started ContainerId has it's ContainerState
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/0b6ea7e020208a3f.
Report an issue: GitHub.