vitessio/vitess · error

duplicate metric name: %s

Error message

duplicate metric name: %s

What it means

UpdateThrottlerConfig rejects AppCheckedMetrics lists containing the same known metric more than once, using a set of already-seen base metric names. Duplicates are ambiguous for the throttler config so the RPC fails fast.

Source

Thrown at go/vt/vtctl/grpcvtctldserver/server.go:2115

	defer panicHandler(&err)

	if req.Enable && req.Disable {
		return nil, errors.New("--enable and --disable are mutually exclusive")
	}

	if req.MetricName != "" && !base.KnownMetricNames.Contains(base.MetricName(req.MetricName)) {
		return nil, fmt.Errorf("unknown metric name: %s", req.MetricName)
	}

	if len(req.AppCheckedMetrics) > 0 {
		specifiedMetrics := map[base.MetricName]bool{}
		for _, metricName := range req.AppCheckedMetrics {
			_, knownMetric, err := base.DisaggregateMetricName(metricName)
			if err != nil {
				return nil, fmt.Errorf("invalid metric name: %s", metricName)
			}
			if _, ok := specifiedMetrics[knownMetric]; ok {
				return nil, fmt.Errorf("duplicate metric name: %s", knownMetric)
			}
			specifiedMetrics[knownMetric] = true
		}
	}

	update := func(throttlerConfig *topodatapb.ThrottlerConfig) *topodatapb.ThrottlerConfig {
		if throttlerConfig == nil {
			throttlerConfig = &topodatapb.ThrottlerConfig{}
		}
		if throttlerConfig.ThrottledApps == nil {
			throttlerConfig.ThrottledApps = make(map[string]*topodatapb.ThrottledAppRule)
		}
		if throttlerConfig.AppCheckedMetrics == nil {
			throttlerConfig.AppCheckedMetrics = make(map[string]*topodatapb.ThrottlerConfig_MetricNames)
		}
		if throttlerConfig.MetricThresholds == nil {
			throttlerConfig.MetricThresholds = make(map[string]float64)
		}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Deduplicate the AppCheckedMetrics list before calling the RPC (compare disaggregated base metric names).
  2. Keep one canonical form per metric (either bare or fully disaggregated) in your tooling.
  3. Pre-parse entries with base.DisaggregateMetricName in the caller to catch dupes early.

Example fix

// before
--app-checked-metrics "loadaverage,loadaverage.mysql"
// after
--app-checked-metrics "loadaverage.mysql"
Defensive patterns

Strategy: validation

Validate before calling

seen := map[base.MetricName]bool{}
for _, m := range req.AppCheckedMetrics {
    known, _, err := base.DisaggregateMetricName(m)
    if err != nil { return err }
    if seen[known] { return fmt.Errorf("duplicate metric %v", known) }
    seen[known] = true
}

Prevention

When it happens

Trigger: Calling UpdateThrottlerConfig with two entries in req.AppCheckedMetrics that disaggregate to the same known metric, e.g. 'loadaverage' and 'loadaverage.mysql' both present.

Common situations: Appending to an existing metrics list in automation without deduplication, or repeating a metric in a CLI comma-list.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/5335af57db8221aa. Report an issue: GitHub.