#4209·gofr

tracing: a failed or unsupported TRACE_EXPORTER installs a BatchSpanProcessor over a nil exporter and silently drops every span

Author: akshat-kumar-singhalCreated Sep 14, 2026Updated Sep 14, 2026

Summary

App.initTracer registers a BatchSpanProcessor over the exporter returned by getExporter without checking whether one was actually produced. When it was not, the TracerProvider is installed with a batch processor that silently discards every span, and the application looks correctly configured for tracing.

pkg/gofr/otel.go on development (9bbdbbe2):

go
exporter, err := a.getExporter(traceExporter, tracerHost, tracerPort, tracerURL)
if err != nil {
	a.container.Error(err)
}

batcher := sdktrace.NewBatchSpanProcessor(exporter)   // exporter may be nil
tp.RegisterSpanProcessor(batcher)

Two ways to reach it

  1. A builder returns an error. The error is logged, then the nil exporter is used anyway.
  2. An unsupported TRACE_EXPORTER. The default: branch of getExporter calls a.container.Errorf("unsupported TRACE_EXPORTER: %s", name) and falls through, returning a nil exporter with a nil error — so even the if err != nil above does not fire.

It does not panic — that is what makes it hard to notice

NewBatchSpanProcessor(nil) is safe: the SDK guards the nil exporter at sdk/trace/batch_span_processor.go:153 (if bsp.e == nil). Confirmed against the pinned go.opentelemetry.io/otel/sdk v1.44.0 — spans are started, ended, and dropped; ForceFlush returns nil.

So there is no crash and no repeated error. There is one error line at startup, after which the service runs with a sampling TracerProvider whose spans go nowhere. TRACE_EXPORTER=otlpp (typo) produces exactly this.

Expected

A failure to build an exporter should degrade to the same place as "tracing not configured": a NeverSample provider, so correlation IDs stay unique and no batch processor is installed over nothing.

Note

#4206 already fixes this as a side effect of moving exporter construction into a registry — exporters.Build returns the NeverSample provider when the builder yields no exporter (pkg/gofr/traces/exporters/provider.go:52-55). Filing separately because the bug is live on development until that merges, and because it is worth fixing on its own terms if #4206 changes shape.

Found by @aryanmehrotra during review of #4205.