SigNoz/signoz · error
invalid_input
invalid_input
Error message
must not specify multiple metric reader type
What it means
Thrown by metricReaderWithCustomRegistry in the OpenMeter instrumentation package when a MetricReader config sets both Periodic and Pull. The OTel SDK config schema allows only one reader type per MetricReader entry, so specifying two is rejected as invalid input.
Source
Thrown at pkg/instrumentation/metric.go:146
if err == nil {
opts = append(opts, sdkmetric.WithReader(r))
} else {
errs = append(errs, err)
}
}
if len(errs) > 0 {
return noop.NewMeterProvider(), noopShutdown, errors.Join(errs...)
}
mp := sdkmetric.NewMeterProvider(opts...)
return mp, mp.Shutdown, nil
}
// metricReaderWithCustomRegistry creates metric readers with custom Prometheus registry support.
func metricReaderWithCustomRegistry(ctx context.Context, r contribsdkconfig.MetricReader, customRegistry *prometheus.Registry) (sdkmetric.Reader, error) {
if r.Periodic != nil && r.Pull != nil {
return nil, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "must not specify multiple metric reader type")
}
if r.Pull != nil {
return pullReaderWithCustomRegistry(ctx, r.Pull.Exporter, customRegistry)
}
return nil, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "no valid metric reader")
}
// pullReaderWithCustomRegistry creates pull readers with custom Prometheus registry support.
func pullReaderWithCustomRegistry(ctx context.Context, exporter contribsdkconfig.MetricExporter, customRegistry *prometheus.Registry) (sdkmetric.Reader, error) {
if exporter.Prometheus != nil {
return prometheusReaderWithCustomRegistry(ctx, exporter.Prometheus, customRegistry)
}
return nil, errors.New(errors.TypeInvalidInput, errors.CodeInvalidInput, "no valid metric exporter")
}
View on GitHub (pinned to 5069bf80b0)
Solutions
- Remove either the `periodic` or `pull` block from the metric reader config so exactly one is set
- If you need both push and pull metrics, define two separate metric reader entries
Example fix
// before
readers:
- periodic: { exporter: { otlp: {} } }
pull: { exporter: { prometheus: {} } }
// after
readers:
- periodic: { exporter: { otlp: {} } }
- pull: { exporter: { prometheus: {} } } Defensive patterns
Strategy: validation
Validate before calling
if r.Periodic != nil && r.Pull != nil { return fmt.Errorf("specify only one of periodic or pull per metric reader") } Prevention
- Validate metric reader config in a config linter before app start
- Keep push (periodic) and pull exporters in separate reader entries
When it happens
Trigger: Passing a contribsdkconfig.MetricReader with both r.Periodic != nil and r.Pull != nil to metricReaderWithCustomRegistry (via meterProviderWithCustomRegistry).
Common situations: YAML config for the metrics subsystem defines both `periodic` and `pull` blocks under the same reader; copy-pasting examples that combine a push and pull exporter in one reader entry.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
AI-assisted analysis of SigNoz/signoz@5069bf80b0 (2026-08-28).
Data as JSON: /api/errors/0c1d7d8ba5553f0a.
Report an issue: GitHub.