jaegertracing/jaeger · error
failed to stop the adaptive sampling aggregator : %w
Error message
failed to stop the adaptive sampling aggregator : %w
What it means
This error wraps failures from aggregator.Close() when the adaptive sampling trace processor shuts down. The aggregator must flush pending sampling statistics and release the distributed lock; if graceful shutdown fails, the close lifecycle hook wraps the underlying error so the collector reports which component failed to stop.
Source
Thrown at cmd/jaeger/internal/processors/adaptivesampling/processor.go:62
tp.telset.Logger,
otelmetrics.NewFactory(tp.telset.MeterProvider),
parts.DistLock,
parts.SamplingStore,
)
if err != nil {
return fmt.Errorf("failed to create the adaptive sampling aggregator: %w", err)
}
agg.Start()
tp.aggregator = agg
return nil
}
func (tp *traceProcessor) close(context.Context) error {
if tp.aggregator != nil {
if err := tp.aggregator.Close(); err != nil {
return fmt.Errorf("failed to stop the adaptive sampling aggregator : %w", err)
}
}
return nil
}
func (tp *traceProcessor) processTraces(_ context.Context, td ptrace.Traces) (ptrace.Traces, error) {
batches := v1adapter.V1BatchesFromTraces(td)
for _, batch := range batches {
for _, span := range batch.Spans {
if span.Process == nil {
span.Process = batch.Process
}
tp.aggregator.HandleRootSpan(span)
}
}
return td, nil
}
View on GitHub (pinned to 806f444784)
Solutions
- Read the wrapped inner error to identify which shutdown step failed (lock release vs worker shutdown)
- Ensure the distributed-lock backend is reachable during shutdown so the aggregator can release its lock
- Give the collector a sufficient shutdown timeout so background sampling workers can exit
- If it recurs, check the sampling store health; repeated Close failures usually indicate an unhealthy backend
Example fix
# before: too-short shutdown kills the aggregator mid-flush # after: allow time for graceful stop in collector config service: telemetry: ... # run collector with a longer shutdown grace period, e.g. # ensure dist-lock backend is up: docker compose up etcd
Defensive patterns
Strategy: try-catch
Validate before calling
if tp.aggregator != nil {
// check backend health before shutdown to anticipate Close failures
if err := healthCheckSamplingStore(ctx); err != nil {
logger.Warn("sampling store unhealthy; Close may fail to release dist lock")
}
} Try / catch
if err := tp.close(ctx); err != nil {
logger.Error("failed to stop adaptive sampling aggregator", log.Error(err))
// decide whether to abort shutdown or continue; inspect wrapped cause
return fmt.Errorf("processor shutdown failed: %w", err)
} Prevention
- Keep the dist-lock backend available during shutdown windows
- Use generous collector shutdown timeouts
- Monitor sampling store health to avoid Close-time failures
- Handle nil aggregator (processor never started) before closing
When it happens
Trigger: Calling close (collector shutdown or test) while tp.aggregator is non-nil and aggregator.Close() returns an error — e.g. the distributed lock cannot be released or background workers fail to stop within the shutdown deadline.
Common situations: Collector shutdown with the sampling store unreachable; the dist-lock backend (etcd/oteld) down at shutdown time so the lock cannot be released; context/deadline expiring before the aggregator's background loop exits.
Related errors
- failed to create the adaptive sampling aggregator: %w
- cannot find factory for trace storage %s: %w
- cannot resolve query interceptors: %w
- cannot find extension '%s' (make sure it's defined earlier i
- extension '%s' is not of expected type '%s'
AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01).
Data as JSON: /api/errors/98aa09cf8fe21a9e.
Report an issue: GitHub.