jaegertracing/jaeger · error

error shutting down cleaner server: %w

Error message

error shutting down cleaner server: %w

What it means

During Shutdown the extension gracefully drains its internal HTTP server with c.server.Shutdown(ctx). If the server cannot stop within the context's deadline or returns another error, it is wrapped as 'error shutting down cleaner server' and propagated from Shutdown, failing the component shutdown.

Source

Thrown at cmd/jaeger/internal/integration/storagecleaner/extension.go:81

		Addr:              ":" + c.config.Port,
		Handler:           mux,
		ReadHeaderTimeout: 3 * time.Second,
	}
	c.telset.Logger.Info("Starting storage cleaner server", zap.String("addr", c.server.Addr))
	go func() {
		if err := c.server.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
			err = fmt.Errorf("error starting cleaner server: %w", err)
			componentstatus.ReportStatus(host, componentstatus.NewFatalErrorEvent(err))
		}
	}()

	return nil
}

func (c *storageCleaner) Shutdown(ctx context.Context) error {
	if c.server != nil {
		if err := c.server.Shutdown(ctx); err != nil {
			return fmt.Errorf("error shutting down cleaner server: %w", err)
		}
	}
	return nil
}

func (*storageCleaner) Dependencies() []component.ID {
	return []component.ID{jaegerstorage.ID}
}

View on GitHub (pinned to 806f444784)

Solutions

  1. Increase the component shutdown timeout so in-flight purge requests can complete
  2. Ensure clients stop issuing purge requests before shutting down the collector
  3. Retry shutdown with a fresh context; if persistent, investigate stuck connections with netstat/ss

Example fix

// before
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
// after
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure no long-running purge requests before shutdown
// optionally poll the /purge endpoint's readiness and let in-flight calls finish

Try / catch

if err := ext.Shutdown(ctx); err != nil {
    if errors.Is(ctx.Err(), context.DeadlineExceeded) {
        // retry with a longer deadline
        ctx2, cancel := context.WithTimeout(context.Background(), 30*time.Second)
        defer cancel()
        err = ext.Shutdown(ctx2)
    }
}

Prevention

When it happens

Trigger: Shutdown() is called while the purge HTTP server still has active connections that do not finish before ctx is canceled, or the underlying listener returns an error during close.

Common situations: A purge request is in flight and the OTel shutdown timeout is shorter than the purge duration; using an already-canceled or very short shutdown context; stalled connections (keep-alive clients) keeping the drain alive.

Related errors


AI-assisted analysis of jaegertracing/jaeger@806f444784 (2026-09-01). Data as JSON: /api/errors/389fc1f984d13aca. Report an issue: GitHub.