vxcontrol/pentagi · error

failed to force flush meter: %w

Error message

failed to force flush meter: %w

What it means

This error is produced by telemetryClient.ForceFlush when the OpenTelemetry metric provider (sdk metric MeterProvider) fails to force-push all queued metric data. It is wrapped so the caller knows the meter leg of the flush failed; logger and tracer errors are reported separately and all are joined with errors.Join.

Source

Thrown at backend/pkg/observability/otelclient.go:90

	}
	if err := c.tracer.Shutdown(ctx); err != nil {
		errs = append(errs, fmt.Errorf("failed to shutdown tracer: %w", err))
	}
	// Always close the connection, even if a provider shutdown failed above, so a
	// stalled flush can't leak the grpc conn.
	if err := c.conn.Close(); err != nil {
		errs = append(errs, fmt.Errorf("failed to close telemetry connection: %w", err))
	}
	return errors.Join(errs...)
}

func (c *telemetryClient) ForceFlush(ctx context.Context) error {
	var errs []error
	if err := c.logger.ForceFlush(ctx); err != nil {
		errs = append(errs, fmt.Errorf("failed to force flush logger: %w", err))
	}
	if err := c.meter.ForceFlush(ctx); err != nil {
		errs = append(errs, fmt.Errorf("failed to force flush meter: %w", err))
	}
	if err := c.tracer.ForceFlush(ctx); err != nil {
		errs = append(errs, fmt.Errorf("failed to force flush tracer: %w", err))
	}
	return errors.Join(errs...)
}

func NewTelemetryClient(ctx context.Context, cfg *config.Config) (TelemetryClient, error) {
	if cfg.TelemetryEndpoint == "" {
		return nil, fmt.Errorf("telemetry endpoint is not set: %w", ErrNotConfigured)
	}

	// grpc.NewClient is non-blocking: it never dials during startup, so a
	// set-but-unreachable collector can't stall main(), and the connection is
	// established (and re-established) lazily in the background — a collector that
	// comes up after the app does connects on its own, without a restart.
	conn, err := grpc.NewClient(
		cfg.TelemetryEndpoint,

View on GitHub (pinned to ea665308ba)

Solutions

  1. Inspect the wrapped error to distinguish deadline vs export failure
  2. Confirm the collector endpoint from cfg.TelemetryEndpoint accepts OTLP gRPC metrics
  3. Extend the context timeout used for the flush
  4. Check collector logs/storage; if metrics were lost, verify collector enablement in docker-compose-observability.yml
Defensive patterns

Strategy: try-catch

Validate before calling

if cfg.TelemetryEndpoint == "" { skip telemetry setup }

Try / catch

if err := client.ForceFlush(ctx); err != nil {
    if strings.Contains(err.Error(), "force flush meter") {
        // metrics leg failed: verify collector metrics receiver
    }
    log.Warnf("metric flush failed: %v", err)
}

Prevention

When it happens

Trigger: Calling ForceFlush(ctx) when the metric reader/exporter cannot deliver pending metrics: ctx cancelled or deadline exceeded, otlpmetricgrpc Export failing because the collector is down, or transient gRPC errors (with WaitForReady the call waits and can hit the ctx deadline).

Common situations: Collector restarted or unreachable during shutdown; large metric batches taking longer than the context timeout; firewall/network issues to the OTLP endpoint (typically :4317).

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/64fbeb58b1176a8b. Report an issue: GitHub.