influxdata/influxdb · error

no metric in progress

Error message

no metric in progress

What it means

PrometheusTextEncoder (core/metric_exporters) implements metric::Reporter for the Prometheus text exposition format. start_metric opens a metric family (stored as Option<(MetricFamily, bool)>), report_observation appends labeled samples, and finishing closes it. report_observation panics with 'no metric in progress' when no start_metric is active - called before start_metric or after the family was finished. (Symmetrically, start_metric asserts 'metric already in progress' if the previous family was never finished.)

Source

Thrown at core/metric_exporters/src/lib.rs:75

            MetricKind::DurationCounter => {
                (format!("{metric_name}_seconds_total"), MetricType::COUNTER)
            }
            MetricKind::DurationGauge => (format!("{metric_name}_seconds"), MetricType::GAUGE),
            MetricKind::DurationHistogram => {
                (format!("{metric_name}_seconds"), MetricType::HISTOGRAM)
            }
        };

        let mut metric = MetricFamily::default();
        metric.set_name(name);
        metric.set_help(description.to_string());
        metric.set_field_type(metric_type);

        self.metric = Some((metric, false))
    }

    fn report_observation(&mut self, attributes: &Attributes, observation: Observation) {
        let (metrics, used) = self.metric.as_mut().expect("no metric in progress");

        let metrics = metrics.mut_metric();

        let mut metric = Metric::default();

        metric.set_label(
            attributes
                .iter()
                .map(|(name, value)| {
                    let mut pair = LabelPair::default();
                    pair.set_name(name.to_string());
                    pair.set_value(value.to_string());
                    pair
                })
                .collect(),
        );

        match observation {

View on GitHub (pinned to d28e26e048)

Solutions

  1. Emit the full ordered sequence per metric: start_metric, one or more report_observation, then finish
  2. When buffering/replaying observations, buffer the (name, description, kind) triple too and replay start_metric first
  3. Wrap the encoder in a struct that tracks 'metric open' state and asserts or logs before misordering
  4. Reuse the stock export paths in the metric crate rather than driving the trait by hand

Example fix

// before
encoder.report_observation(&attrs, obs);  // no start_metric -> panic

// after
encoder.start_metric("requests", "count", MetricKind::U64Counter);
encoder.report_observation(&attrs, obs);
// finish_metric() when done
Defensive patterns

Strategy: validation

Validate before calling

// when replaying buffered observations, replay start_metric first
for (meta, obs) in buffered {
    encoder.start_metric(meta.name, meta.description, meta.kind);
    for (attrs, observation) in obs {
        encoder.report_observation(&attrs, observation);
    }
    // finish per your Reporter impl's contract
}

Prevention

When it happens

Trigger: Hand-driving the encoder out of order: report_observation without a preceding start_metric; reporting after the current family was finished; replaying observations captured from another reporter without replaying the start_metric call first.

Common situations: Writing custom exporters that wrap or buffer the Prometheus encoder; refactors that reorder start/report/finish; batch export logic that drops the start call for empty attribute sets.

Related errors


AI-assisted analysis of influxdata/influxdb@d28e26e048 (2026-08-16). Data as JSON: /api/errors/3bea56280fdb7f97. Report an issue: GitHub.