microsoft/aspire · error
metric exporter
Error message
metric exporter: %w
What it means
setupOTel wraps the error from otlpmetricgrpc.New, which builds the gRPC OTLP metric exporter. Creation fails when the OTLP endpoint/URL is invalid or exporter options (TLS, headers, timeout) are inconsistent. The wrap "metric exporter: %w" preserves the root cause.
Solutions
- Check the metrics OTLP endpoint for a valid scheme and host:port and log the unwrapped error.
- Match the endpoint to the exporter type: use WithEndpoint(host:port) or WithEndpointURL(full url) consistently for the SDK version in use.
- Verify the collector/dashboard metrics port is open and reachable.
- Keep trace and metric exporters pointed at the same protocol (both grpc or both http).
Example fix
// before
metricExp, err := otlpmetricgrpc.New(ctx, metricOpts...)
if err != nil {
return nil, fmt.Errorf("metric exporter: %w", err)
}
// after
if ep := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT"); ep == "" {
log.Println("OTEL_EXPORTER_OTLP_ENDPOINT not set; metrics disabled")
return nil, nil
}
metricExp, err := otlpmetricgrpc.New(ctx, metricOpts...)
if err != nil {
return nil, fmt.Errorf("metric exporter: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
ep := os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT")
if u, err := url.Parse(ep); err != nil || u.Host == "" {
return fmt.Errorf("invalid metrics OTLP endpoint %q", ep)
} Try / catch
if err := setupOTel(...); err != nil {
log.Printf("metrics exporter unavailable: %v", err) // degrade gracefully
} Prevention
- Validate endpoint host:port before building the exporter.
- Use the same endpoint style for all OTLP signals.
- Confirm collector ports are open before startup.
- Pin OTLP SDK versions.
When it happens
Trigger: otlpmetricgrpc.New returns an error due to a malformed endpoint URL, invalid retry/timeout configuration, or bad TLS credentials, when setting up metrics via setupOTel.
Common situations: Wrong OTEL_EXPORTER_OTLP_ENDPOINT value, endpoint given as http://host:port while WithEndpoint expects host:port, misconfigured metrics collector address.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- log exporter
- trace exporter
- otel resource
- runtime metrics
- Histogram data point has bucket counts without any explicit…
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/fe3e4b7ae124cd86.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Cli/Templating/Templates/go-starter/api/telemetry.go:70
traceOpts = append(traceOpts, otlptracegrpc.WithHeaders(headers))
}
traceExp, err := otlptracegrpc.New(ctx, traceOpts...)
if err != nil {
return nil, fmt.Errorf("trace exporter: %w", err)
}
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(traceExp),
sdktrace.WithResource(res),
)
otel.SetTracerProvider(tp)
metricOpts := []otlpmetricgrpc.Option{}
if len(headers) > 0 {
metricOpts = append(metricOpts, otlpmetricgrpc.WithHeaders(headers))
}
metricExp, err := otlpmetricgrpc.New(ctx, metricOpts...)
if err != nil {
return nil, fmt.Errorf("metric exporter: %w", err)
}
mp := sdkmetric.NewMeterProvider(
sdkmetric.WithReader(sdkmetric.NewPeriodicReader(metricExp)),
sdkmetric.WithResource(res),
)
otel.SetMeterProvider(mp)
if err := runtime.Start(runtime.WithMeterProvider(mp)); err != nil {
return nil, fmt.Errorf("runtime metrics: %w", err)
}
logOpts := []otlploggrpc.Option{}
if len(headers) > 0 {
logOpts = append(logOpts, otlploggrpc.WithHeaders(headers))
}
logExp, err := otlploggrpc.New(ctx, logOpts...)
if err != nil {
return nil, fmt.Errorf("log exporter: %w", err)View on GitHub (pinned to 25830f84bd)