{"record":{"id":"b83de67e67bad06f","repo":"vxcontrol/pentagi","slug":"failed-to-force-flush-logger-w","errorCode":null,"errorMessage":"failed to force flush logger: %w","messagePattern":"failed to force flush logger: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/pkg/observability/otelclient.go","lineNumber":87,"sourceCode":"\t}\n\tif err := c.meter.Shutdown(ctx); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to shutdown meter: %w\", err))\n\t}\n\tif err := c.tracer.Shutdown(ctx); err != nil {\n\t\terrs = append(errs, fmt.Errorf(\"failed to shutdown tracer: %w\", err))\n\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","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/vxcontrol/pentagi/blob/ea665308baaff015b226f308438a68d929d0f29b/backend/pkg/observability/otelclient.go#L69-L105","documentation":"This error is produced by telemetryClient.ForceFlush in backend/pkg/observability/otelclient.go when the underlying OpenTelemetry log provider fails to flush its buffered log records within the given context. It wraps the original SDK error so the caller knows which of the three pipelines (logger, meter, tracer) failed. The function collects errors from all three components and joins them with errors.Join.","triggerScenarios":"Calling ForceFlush(ctx) when the sdklog LoggerProvider's batch processor cannot export pending log records: ctx deadline exceeded before the batch exporter finishes, the OTLP gRPC exporter returning an error, or the collector rejecting logs.","commonSituations":"Shutdown-time flushes during application exit with an unreachable or slow OpenTelemetry Collector; short-lived contexts cancelled before the batch processor can drain; network partitions between the app and the collector endpoint.","solutions":["Check the wrapped cause (%w) to see whether it is a context deadline or an export failure and address that first","Verify the OTLP collector at cfg.TelemetryEndpoint is reachable (docker compose observability stack up, correct port 4317)","Increase the flush timeout passed via ctx or retry the flush with a fresh context","If seen at shutdown, ensure the collector is healthy before stopping the app, or accept and log the dropped logs"],"exampleFix":"// before\nif err := client.ForceFlush(context.Background()); err != nil {\n    return err\n}\n// after\nctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)\ndefer cancel()\nif err := client.ForceFlush(ctx); err != nil {\n    log.Warnf(\"telemetry flush incomplete: %v\", err) // don't fail shutdown on telemetry\n}","handlingStrategy":"try-catch","validationCode":"if client == nil { /* telemetry disabled, skip flush */ }","typeGuard":null,"tryCatchPattern":"if err := client.ForceFlush(ctx); err != nil {\n    var joined interface{ Unwrap() []error }\n    if errors.As(err, &joined) { /* inspect each leg */ }\n    log.Warnf(\"flush failed (non-fatal): %v\", err)\n}","preventionTips":["Always pass a context with adequate timeout for flush","Use errors.Is/As on the joined error to identify the failing leg","Check collector health before shutdown flushes","Treat telemetry flush errors as non-fatal to application shutdown"],"tags":["opentelemetry","flush","logging","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"}