cilium/cilium · warning

failed to unregister metric: dns_response_types_total,

Error message

failed to unregister metric: dns_response_types_total,

What it means

Same failure mode as 2927/2928 but for the dns_response_types_total collector: registry.Unregister(h.responseTypes) returned false during Deinit, so the bucketed response-type histogram was absent from the registry. The error is joined into Deinit's aggregate error.

Source

Thrown at pkg/hubble/metrics/dns/handler.go:180

				newLabels = append(newLabels, dns.Query)
			}
			h.responseTypes.WithLabelValues(newLabels...).Inc()
		}
	}

	return nil
}

func (h *dnsHandler) Deinit(registry *prometheus.Registry) error {
	var errs error
	if !registry.Unregister(h.queries) {
		errs = errors.Join(errs, fmt.Errorf("failed to unregister metric: %v,", "dns_queries_total"))
	}
	if !registry.Unregister(h.responses) {
		errs = errors.Join(errs, fmt.Errorf("failed to unregister metric: %v,", "dns_responses_total"))
	}
	if !registry.Unregister(h.responseTypes) {
		errs = errors.Join(errs, fmt.Errorf("failed to unregister metric: %v,", "dns_response_types_total"))
	}
	return errs
}

func (h *dnsHandler) HandleConfigurationUpdate(cfg *api.MetricConfig) error {
	return h.SetFilters(cfg)
}

func (h *dnsHandler) SetFilters(cfg *api.MetricConfig) error {
	var err error
	h.AllowList, err = filters.BuildFilterList(context.Background(), cfg.IncludeFilters, filters.DefaultFilters(slog.Default()))
	if err != nil {
		return err
	}
	h.DenyList, err = filters.BuildFilterList(context.Background(), cfg.ExcludeFilters, filters.DefaultFilters(slog.Default()))
	if err != nil {
		return err
	}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Call Init (and SetFilters) successfully on this registry before Deinit
  2. Pass the same registry instance used during registration
  3. Ignore or tolerate false Unregister returns in tests if intentional

Example fix

// before
h := newDNSHandler(...)
h.Deinit(registry) // never Init'ed
// after
h.Init(registry)
// ...
h.Deinit(registry)
Defensive patterns

Strategy: type-guard

Type guard

func canDeinit(h *dnsHandler, reg *prometheus.Registry) bool {
    return h != nil && h.responseTypes != nil && reg != nil
}

Try / catch

if err := h.Deinit(reg); err != nil {
    logger.Warn("dns deinit incomplete", "err", err)
}

Prevention

When it happens

Trigger: Deinit when h.responseTypes is not registered in the supplied registry — no prior successful Init, double Deinit, or registry mismatch.

Common situations: Handler teardown during dynamic metric reconfiguration where the collector was never added; tests constructing a handler manually and calling Deinit on an empty registry.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/1cd9974277fa8fb9. Report an issue: GitHub.