{"record":{"id":"0b888e14574b1c62","repo":"vxcontrol/pentagi","slug":"failed-to-force-flush-tracer-w","errorCode":null,"errorMessage":"failed to force flush tracer: %w","messagePattern":"failed to force flush tracer: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/observability/otelclient.go","lineNumber":93,"sourceCode":"\t}\n\t// Always close the connection, even if a provider shutdown failed above, so a\n\t// stalled flush can't leak the grpc conn.\n\tif err := c.conn.Close(); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to close telemetry connection: %w\", err))\n\t}\n\treturn errors.Join(errs...)\n}\n\nfunc (c *telemetryClient) ForceFlush(ctx context.Context) error {\n\tvar errs []error\n\tif err := c.logger.ForceFlush(ctx); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to force flush logger: %w\", err))\n\t}\n\tif err := c.meter.ForceFlush(ctx); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to force flush meter: %w\", err))\n\t}\n\tif err := c.tracer.ForceFlush(ctx); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to force flush tracer: %w\", err))\n\t}\n\treturn errors.Join(errs...)\n}\n\nfunc NewTelemetryClient(ctx context.Context, cfg *config.Config) (TelemetryClient, error) {\n\tif cfg.TelemetryEndpoint == \"\" {\n\t\treturn nil, fmt.Errorf(\"telemetry endpoint is not set: %w\", ErrNotConfigured)\n\t}\n\n\t// grpc.NewClient is non-blocking: it never dials during startup, so a\n\t// set-but-unreachable collector can't stall main(), and the connection is\n\t// established (and re-established) lazily in the background — a collector that\n\t// comes up after the app does connects on its own, without a restart.\n\tconn, err := grpc.NewClient(\n\t\tcfg.TelemetryEndpoint,\n\t\tgrpc.WithTransportCredentials(insecure.NewCredentials()),\n\t\tgrpc.WithDefaultCallOptions(grpc.WaitForReady(true)),\n\t)","sourceCodeStart":75,"sourceCodeEnd":111,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/observability/otelclient.go#L75-L111","documentation":"This error is produced by telemetryClient.ForceFlush when the trace provider fails to force-flush pending spans. It is wrapped with context naming the tracer leg, joined with any logger/meter flush errors via errors.Join.","triggerScenarios":"Calling ForceFlush(ctx) while otlptracegrpc cannot export buffered spans: ctx deadline exceeded, collector unavailable, exporter returning a retryable/permanent export error.","commonSituations":"Graceful shutdown with a down or overloaded OpenTelemetry Collector; spans accumulated during a burst exceeding the flush timeout; DNS/network failures to the telemetry endpoint.","solutions":["Read the joined/wrapped cause for the real exporter error","Verify collector reachability at cfg.TelemetryEndpoint (port 4317)","Use a longer-lived context for shutdown flushes","Treat as non-fatal at shutdown: log and continue, since spans are typically advisory"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"if client == nil { return } // telemetry never initialized","typeGuard":null,"tryCatchPattern":"if err := client.ForceFlush(ctx); err != nil {\n    log.Warnf(\"span flush failed (spans may be dropped): %v\", err)\n}","preventionTips":["Flush with a fresh, long-enough context at shutdown","Keep the collector within the same network namespace where possible","Avoid canceling the parent context mid-flush","Consider a bounded retry for tracer flush"],"tags":["opentelemetry","flush","tracing","grpc"],"backgroundTag":"otlp-flush-failed","analyzedSha":"ea665308baaff015b226f308438a68d929d0f29b","analyzedAt":"2026-09-01T14:16:31.421Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}