influxdata/influxdb · error

all types covered

Error message

all types covered

What it means

panic_logging's PanicCounters builds a HashMap from PanicType::all() and inc() does counters.get(&panic_type).expect("all types covered"). The map is populated from the same enum's all() list, so the lookup fails only if the PanicType enum and its all() implementation have diverged — i.e. a variant exists that all() does not return. This is a maintenance invariant: it fires on a variant that was added without updating all(), not on runtime data.

Source

Thrown at core/panic_logging/src/lib.rs:194

impl Metrics {
    fn new(metrics: &metric::Registry) -> Self {
        let metric = metrics.register_metric::<U64Counter>(
            "thread_panic_count",
            "number of thread panics observed",
        );

        Self {
            counters: PanicType::all()
                .iter()
                .map(|t| (*t, metric.recorder(&[("type", t.name())])))
                .collect(),
        }
    }

    fn inc(&self, panic_type: PanicType) {
        self.counters
            .get(&panic_type)
            .expect("all types covered")
            .inc(1);
    }
}

#[cfg(test)]
mod tests {
    use std::panic::panic_any;

    use metric::{Attributes, Metric};
    use test_helpers::{assert_contains, maybe_start_logging, tracing::TracingCapture};

    use super::*;

    fn assert_count(metrics: &metric::Registry, t: &'static str, count: u64) {
        let got = metrics
            .get_instrument::<Metric<U64Counter>>("thread_panic_count")
            .expect("failed to read metric")
            .get_observer(&Attributes::from(&[("type", t)]))

View on GitHub (pinned to d28e26e048)

Solutions

  1. If you added a PanicType variant, add it to PanicType::all() (or replace the manual list with a match that has a wildcard/error arm).
  2. cargo clean and rebuild to rule out stale artifacts mixing enum layouts.
  3. Make the invariant un-breakable: derive the list (e.g. strum::EnumIter) or use a match returning the name with `#[deny(unreachable_patterns)]`.
  4. Upstream-style hardening: fall back to an 'unknown' counter instead of expect so panic logging never panics.

Example fix

// before
fn all() -> Vec<PanicType> {
    vec![/* manually maintained list; new variants silently missing */]
}

// after (compiler-enforced exhaustiveness)
fn all() -> Vec<PanicType> {
    // strum::EnumIter: `PanicType::iter().collect()`
    // or a `fn name(&self) -> &str` match which fails to compile
    // when a variant is added without a arm.
    PanicType::iter().collect()
}
Defensive patterns

Strategy: type-guard

Validate before calling

// compile-time or startup-time exhaustiveness check when you touch PanicType
#[test]
fn panic_types_all_is_exhaustive() {
    // requires an iterator derive (strum) or a match-based name():
    // adding a variant without updating all() should fail here, not in prod
    assert_eq!(PanicType::all().len(), EXPECTED_VARIANT_COUNT);
}

Type guard

// if you maintain this crate: encode exhaustiveness in the type
type PanicCounters = EnumMap<PanicType, U64Counter>; // keyed by variant, cannot miss

// or: fn counters() -> impl Fn(PanicType) -> U64Counter built from a
// `match` with per-variant arms (a new variant breaks the build).

Prevention

When it happens

Trigger: A new PanicType variant added to the enum without extending PanicType::all(); any panic of that new type then panics here while incrementing its counter, replacing the very panic being logged. Also possible with a stale/inconsistent build mixing old and new crate artifacts.

Common situations: Contributing a new panic category to panic_logging; version-skewed incremental builds after rebasing; feature-gated variants compiled in one crate instance but not in the instance that built all().

Related errors


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