{"record":{"id":"66c8478cad2d8c43","repo":"netbirdio/netbird","slug":"stop-error-after-context-done-stop-error-w-con","errorCode":null,"errorMessage":"stop error after context done. Stop error: %w. Context done: %w","messagePattern":"stop error after context done\\. Stop error: %w\\. Context done: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/embed/embed.go","lineNumber":289,"sourceCode":"\t// TODO: make after-startup backoff err available\n\trun := make(chan struct{})\n\tclientErr := make(chan error, 1)\n\tgo func() {\n\t\tif err := client.Run(run, \"\"); err != nil {\n\t\t\tclientErr <- err\n\t\t}\n\t}()\n\n\tselect {\n\tcase <-startCtx.Done():\n\t\t// ConnectClient.Stop now cancels its own run context and waits for the\n\t\t// run loop to tear the engine down, so this cancel() is no longer\n\t\t// required to break the deadlock and could be removed. It is kept as a\n\t\t// defensive belt-and-suspenders: cancelling the parent context first\n\t\t// guarantees the run loop is unblocked even if Stop's contract regresses.\n\t\tcancel()\n\t\tif stopErr := client.Stop(); stopErr != nil {\n\t\t\treturn fmt.Errorf(\"stop error after context done. Stop error: %w. Context done: %w\", stopErr, startCtx.Err())\n\t\t}\n\t\treturn startCtx.Err()\n\tcase err := <-clientErr:\n\t\treturn fmt.Errorf(\"startup: %w\", err)\n\tcase <-run:\n\t}\n\n\tc.connect = client\n\tc.cancel = cancel\n\n\treturn nil\n}\n\n// Stop gracefully stops the client.\n// Pass a context with a deadline to limit the time spent waiting for the engine to stop.\nfunc (c *Client) Stop(ctx context.Context) error {\n\tc.mu.Lock()\n\tdefer c.mu.Unlock()","sourceCodeStart":271,"sourceCodeEnd":307,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/embed/embed.go#L271-L307","documentation":"Returned by Client.Start when the caller's startCtx is cancelled or its deadline expires while the engine is still coming up, and additionally ConnectClient.Stop reports an error during the forced teardown. The message wraps both the stop error and the context error, so the primary cause is almost always 'startup did not finish before the deadline' with a secondary teardown failure.","triggerScenarios":"Client.Start with a short-deadline context on a slow network; management server slow to sync the network map; engine start blocked on firewall/DNS/interface setup. The stop error can be any engine teardown error occurring while unwinding.","commonSituations":"First connection on constrained or far-away networks (handshake + sync exceeds a few seconds); strict deadlines copied from unit tests into production; management under load. Users often misread this as a stop bug when the actionable half is the deadline.","solutions":["Increase or remove the deadline on the context passed to Start; engine startup legitimately takes seconds.","Fix the underlying slowness: verify management reachability/latency, DNS resolution, and peer connectivity to the management port.","Retry Start with a fresh client instance and backoff for transient slowness.","If the stop error itself is the mystery, capture it from the wrapped message and investigate teardown separately."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 2*time.Second)\nerr := client.Start(ctx)\n\n// after\nctx, cancel := context.WithTimeout(ctx, 60*time.Second)\nerr := client.Start(ctx)","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := client.Start(startCtx); err != nil {\n    if errors.Is(err, context.DeadlineExceeded) || strings.Contains(err.Error(), \"context done\") {\n        // widen the deadline and retry with a fresh client\n    }\n}","preventionTips":["Budget startup deadlines in tens of seconds, not single digits.","Measure normal startup time in your environment and set the deadline from data."],"tags":["startup","timeout","lifecycle","embed"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}