microsoft/aspire · error

otel resource

Error message

otel resource: %w

What it means

setupOTel wraps a failure from the OpenTelemetry SDK's resource.Merge/resource.NewWithAttributes call: building the identifying resource (service.name etc.) that is attached to traces, metrics, and logs. A wrapped "otel resource: %w" error means the telemetry resource could not be constructed, so the starter API aborts startup before installing providers.

Solutions

  1. Inspect and fix OTEL_RESOURCE_ATTRIBUTES / OTEL_SERVICE_NAME env values (must be valid key=value pairs per the OTel spec)
  2. Align the OTel SDK and semconv package versions so resource.Default()'s schema URL matches semconv.SchemaURL (upgrade both together)
  3. Unset conflicting OTEL_RESOURCE_ATTRIBUTES temporarily to confirm the env var is the cause
  4. As a last resort, construct the resource solely with resource.NewWithAttributes instead of merging with resource.Default()

Example fix

// before
res, err := resource.Merge(resource.Default(), resource.NewWithAttributes(semconv.SchemaURL, semconv.ServiceName(serviceName)))
if err != nil {
	return nil, fmt.Errorf("otel resource: %w", err)
}

// after
// e.g. fix the injected env first:
// OTEL_RESOURCE_ATTRIBUTES=service.namespace=aspire  (valid k=v list)
// or skip conflicting defaults:
res, err := resource.NewWithAttributes(semconv.SchemaURL, semconv.ServiceName(serviceName))
if err != nil {
	return nil, fmt.Errorf("otel resource: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

if attrs := os.Getenv("OTEL_RESOURCE_ATTRIBUTES"); !validOTelAttrs(attrs) {
	return errors.New("invalid OTEL_RESOURCE_ATTRIBUTES")
}

Try / catch

shutdown, err := setupOTel(ctx, serviceName)
if err != nil {
	// optional: log and continue without telemetry
	log.Printf("telemetry disabled: %v", err)
	shutdown = func(context.Context) error { return nil }
}

Prevention

When it happens

Trigger: resource.Merge returns an error — in practice when the default resource detection (OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME env parsing, host/OS detectors) produces conflicting schema URLs or invalid attributes, merged with the semconv v1.40.0 resource built here in the go-starter template's main().

Common situations: Malformed OTEL_RESOURCE_ATTRIBUTES or OTEL_SERVICE_NAME environment variables injected alongside OTEL_EXPORTER_OTLP_ENDPOINT; conflicting schema URLs between resource.Default() and the explicit semconv.SchemaURL after an OTel SDK version upgrade; corrupted env in containers where Aspire injects OTLP config.

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 microsoft/aspire@25830f84bd (2026-09-16). Data as JSON: /api/errors/9260e229eb442aaa. Report an issue: GitHub.

Appendix: source

Thrown at src/Aspire.Cli/Templating/Templates/go-starter/api/telemetry.go:45

)

// setupOTel returns a shutdown func that flushes pending telemetry.
func setupOTel(ctx context.Context, serviceName string) (func(context.Context) error, error) {
	if os.Getenv("OTEL_EXPORTER_OTLP_ENDPOINT") == "" {
		// No exporter configured — install no-op providers so the app still runs
		// (e.g., outside of `aspire run`).
		return func(context.Context) error { return nil }, nil
	}

	res, err := resource.Merge(
		resource.Default(),
		resource.NewWithAttributes(
			semconv.SchemaURL,
			semconv.ServiceName(serviceName),
		),
	)
	if err != nil {
		return nil, fmt.Errorf("otel resource: %w", err)
	}

	headers := otlpHeaders()

	traceOpts := []otlptracegrpc.Option{}
	if len(headers) > 0 {
		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)

View on GitHub (pinned to 25830f84bd)