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
- Inspect and fix OTEL_RESOURCE_ATTRIBUTES / OTEL_SERVICE_NAME env values (must be valid key=value pairs per the OTel spec)
- Align the OTel SDK and semconv package versions so resource.Default()'s schema URL matches semconv.SchemaURL (upgrade both together)
- Unset conflicting OTEL_RESOURCE_ATTRIBUTES temporarily to confirm the env var is the cause
- 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
- Keep OTel SDK and semconv package versions aligned
- Validate OTEL_RESOURCE_ATTRIBUTES/OTEL_SERVICE_NAME env values
- Fail-soft: consider running without telemetry instead of aborting startup
- Pin the OTel resource schema URL consistently across exporters
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
- log exporter
- metric exporter
- trace exporter
- ASPIRE_REMOTE_APPHOST_TOKEN environment variable is not set
- Resource limit of reached. Resource ' ' will not be added.
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)