{"record":{"id":"12e16475b1c773f6","repo":"kubernetes/kops","slug":"already-started","errorCode":null,"errorMessage":"already started","messagePattern":"already started","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/otel/otlptracefile/client.go","lineNumber":59,"sourceCode":"\tvar cfg Config\n\tfor _, option := range opts {\n\t\toption(&cfg)\n\t}\n\n\tc := &client{\n\t\tcfg: cfg,\n\t}\n\n\treturn c\n}\n\n// Start implements otlptrace.Client.\nfunc (c *client) Start(ctx context.Context) error {\n\tc.writerMutex.Lock()\n\tdefer c.writerMutex.Unlock()\n\n\tif c.writer != nil {\n\t\treturn fmt.Errorf(\"already started\")\n\t}\n\n\tw, err := newWriter(c.cfg)\n\tif err != nil {\n\t\treturn err\n\t}\n\tc.writer = w\n\n\treturn nil\n}\n\n// Stop implements otlptrace.Client.\nfunc (c *client) Stop(ctx context.Context) error {\n\tc.writerMutex.Lock()\n\tdefer c.writerMutex.Unlock()\n\n\tif c.writer != nil {\n\t\terr := c.writer.Close()","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/otel/otlptracefile/client.go#L41-L77","documentation":"The otlptracefile client implements the otlptrace.Client interface; Start initializes the file writer and may only be called once. If Start is invoked while c.writer is already non-nil (a previous Start succeeded), it returns \"already started\" to prevent re-initializing and clobbering the open trace file.","triggerScenarios":"Calling client.Start(ctx) twice without an intervening Shutdown; registering the same otlptracefile client with two tracers that both call Start.","commonSituations":"Application bootstrap code that starts the exporter in two places (e.g. both main and an init path); hot-reload logic re-calling Start on config change without shutting down first.","solutions":["Call Start only once per client instance; guard with a sync.Once or a started flag.","Call Shutdown/Stop before invoking Start again, or create a fresh client instance.","Share one tracer provider instead of creating multiple ones around the same client."],"exampleFix":"// before\nclient.Start(ctx)\nclient.Start(ctx) // panics path: already started\n// after\nvar once sync.Once\nonce.Do(func() { client.Start(ctx) })","handlingStrategy":"try-catch","validationCode":"var started bool\nfunc startOnce(c otlptrace.Client, ctx context.Context) error {\n    if started { return nil }\n    started = true\n    return c.Start(ctx)\n}","typeGuard":null,"tryCatchPattern":"if err := client.Start(ctx); err != nil {\n    if strings.Contains(err.Error(), \"already started\") {\n        return nil // idempotent start\n    }\n    return err\n}","preventionTips":["Wrap exporter Start in sync.Once","Keep exporter lifecycle in one bootstrap location","Call Shutdown before any restart of the exporter"],"tags":["opentelemetry","lifecycle","exporter"],"backgroundTag":"double-start","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}