vectordotdev/vector · critical

unexpected metric

Error message

unexpected metric

What it means

The Datadog traces sink is partitioned by API key and only accepts Trace events. Its Partitioner::partition implementation asserts the event kind: receiving a Metric or Log event is a programming/config error and panics immediately.

Solutions

  1. Fix the topology so only Trace events reach the datadog traces sink (route explicitly on the event type)
  2. Replace wildcard ('*') routes with explicit type-scoped routes, or add a filter/route transform checking .message_type or event kind before the sink
  3. Run `vector validate` / `vector graph` to inspect which sources/transforms feed the sink
  4. If the events are intended, use the datadog logs sink or metrics sink for those types instead

Example fix

// before (vector.toml style)
[sinks.datadog_traces]
inputs = ["*"]
// after
[sinks.datadog_traces]
inputs = ["traces_only"]
// where 'traces_only' is a route that passes only Trace events
Defensive patterns

Strategy: validation

Validate before calling

// before wiring the sink, assert event kinds on the input path
assert!(events.iter().all(|e| matches!(e, Event::Trace(_))), "traces sink received non-trace events");

Type guard

fn only_traces(events: &[Event]) -> bool { events.iter().all(|e| matches!(e, Event::Trace(_))) }

Prevention

When it happens

Trigger: An event of type Metric or Log reaches the datadog traces sink — typically via a misconfigured topology where a route or wildcard ('*') sends non-trace events into this sink, or a transform mislabels event types.

Common situations: A wildcard route matching all event types and one branch pointing at the traces sink; pipelines where logs are mistakenly routed to the traces sink; tests constructing the sink with synthetic non-trace events.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/a10018e6daad90d6. Report an issue: GitHub.

Appendix: source

Thrown at src/sinks/datadog/traces/sink.rs:48

pub(crate) struct PartitionKey {
    pub(crate) api_key: Option<Arc<str>>,
    pub(crate) env: Option<String>,
    pub(crate) hostname: Option<String>,
    pub(crate) agent_version: Option<String>,
    // Those two last fields are configuration value and not a per-trace/span information, they come from the Datadog
    // trace-agent config directly: https://github.com/DataDog/datadog-agent/blob/0f73a78/pkg/trace/config/config.go#L293-L294
    pub(crate) target_tps: Option<i64>,
    pub(crate) error_tps: Option<i64>,
}

impl Partitioner for EventPartitioner {
    type Item = Event;
    type Key = PartitionKey;

    fn partition(&self, item: &Self::Item) -> Self::Key {
        match item {
            Event::Metric(_) => {
                panic!("unexpected metric");
            }
            Event::Log(_) => {
                panic!("unexpected log");
            }
            Event::Trace(t) => PartitionKey {
                api_key: item.metadata().datadog_api_key(),
                env: t
                    .get(event_path!("env"))
                    .map(|s| s.to_string_lossy().into_owned()),
                hostname: log_schema().host_key().and_then(|key| {
                    t.get((PathPrefix::Event, key))
                        .map(|s| s.to_string_lossy().into_owned())
                }),
                agent_version: t
                    .get(event_path!("agent_version"))
                    .map(|s| s.to_string_lossy().into_owned()),
                target_tps: t
                    .get(event_path!("target_tps"))

View on GitHub (pinned to bdb87aeaa4)