vectordotdev/vector · error
`docker_logs.stream` must exist in the metadata
Error message
`docker_logs.stream` must exist in the metadata
What it means
In line_agg_adapter's Vector-namespace branch, the stream tag used to group multiline messages is read with log.get(metadata_path!(DockerLogsConfig::NAME, STREAM)).expect("`docker_logs.stream` must exist in the metadata"). The docker_logs source inserts this metadata (stdout/stderr) when it creates each event, so the expect asserts that the event passed through that insertion stage unchanged.
Source
Thrown at src/sources/docker_logs/mod.rs:1353
log_namespace: LogNamespace,
) -> impl Stream<Item = LogEvent> {
let line_agg_in = inner.map(move |mut log| {
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,View on GitHub (pinned to 3708c39b12)
Solutions
- Verify events still carry the docker_logs.stream metadata (inspect with a console sink) with the same config minus multiline
- Remove any custom stages between the source and the aggregator
- Patch: fall back to Bytes::new() for the stream value with a warning
- Report upstream and upgrade
Example fix
// before
let stream_value = log
.get(metadata_path!(DockerLogsConfig::NAME, STREAM))
.expect("`docker_logs.stream` must exist in the metadata");
// after
let stream_value = log
.get(metadata_path!(DockerLogsConfig::NAME, STREAM))
.unwrap_or_else(|| {
warn!(message = "event missing docker_logs.stream metadata");
&Value::Bytes(Bytes::new())
}); Defensive patterns
Strategy: validation
Validate before calling
let stream_value = log
.get(metadata_path!(DockerLogsConfig::NAME, STREAM))
.cloned()
.unwrap_or_else(|| {
warn!(message = "missing docker_logs.stream metadata");
Value::Bytes(Bytes::new())
}); Type guard
fn has_stream_metadata(log: &LogEvent) -> bool {
log.get(metadata_path!(DockerLogsConfig::NAME, STREAM)).is_some()
} Try / catch
match log.get(metadata_path!(DockerLogsConfig::NAME, STREAM)) {
Some(v) => v.coerce_to_bytes(),
None => { warn!("missing stream metadata"); Bytes::new() }
} Prevention
- Insert source metadata and consume it through shared constants so they cannot drift
- Test Vector-namespace events end to end whenever adding stages before aggregation
- Default missing grouping keys to an empty value and log, instead of expecting
When it happens
Trigger: An event reaching the aggregator without docker_logs source metadata - a regression or a custom stage between the source and line_agg that drops or rebuilds metadata, while multiline is enabled with log_namespace = true.
Common situations: Vector upgrades changing source-metadata insertion, forks inserting transforms before aggregation.
Related errors
- `.` must exist in the event
- `message` must exist in the event
- stream must exist in the event
- 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/d6aae89aaa7217e1.
Report an issue: GitHub.