{"record":{"id":"0918b704e78812a5","repo":"netbirdio/netbird","slug":"dial-context-w","errorCode":null,"errorMessage":"dial context: %w","messagePattern":"dial context: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/grpc/dialer.go","lineNumber":62,"sourceCode":"\t}\n\n\tconnCtx, cancel := context.WithTimeout(ctx, 30*time.Second)\n\tdefer cancel()\n\n\topts := []grpc.DialOption{\n\t\ttransportOption,\n\t\tWithCustomDialer(tlsEnabled, component),\n\t\tgrpc.WithBlock(),\n\t\tgrpc.WithKeepaliveParams(keepalive.ClientParameters{\n\t\t\tTime:    30 * time.Second,\n\t\t\tTimeout: 10 * time.Second,\n\t\t}),\n\t}\n\topts = append(opts, extraOpts...)\n\n\tconn, err := grpc.DialContext(connCtx, addr, opts...)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"dial context: %w\", err)\n\t}\n\n\treturn conn, nil\n}\n","sourceCodeStart":44,"sourceCodeEnd":67,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/grpc/dialer.go#L44-L67","documentation":"CreateConnection failed at grpc.DialContext. Because the dial uses grpc.WithBlock and a 30-second context timeout, the returned error is whatever blocked the connection until the deadline: context.DeadlineExceeded when the server never became reachable, or transport-level failures such as connection refused, TLS x509 verification errors (certificate not trusted by the system pool or the embedded fallback roots), or DNS resolution failures from the custom dialer. The %w wrap preserves the gRPC cause for errors.Is/As inspection.","triggerScenarios":"Management or signal service down or unreachable at addr; wrong host/port in the configuration; TLS enabled against a server whose certificate chain is not in SystemCertPool nor the embedded roots; a custom dialer/proxy path (WebSocket component like /management or /signal) failing; network offline or DNS broken so WithBlock exhausts the 30s window.","commonSituations":"Self-hosted NetBird with a self-signed or privately-signed CA not installed on the client host; typo'd management URL; firewall blocking the gRPC port; the 30s dial timeout being too short on high-latency or proxy-chained networks; system cert pool unavailable on stripped-down containers causing fallback roots that do not trust the server.","solutions":["Check the wrapped error class first: errors.Is(err, context.DeadlineExceeded) means unreachable, x509 errors mean trust, connection refused means port/service","Verify the service is listening on the configured address and the URL scheme/port match the deployment (443 vs custom)","Install the CA on the client OS trust store or serve a publicly-trusted certificate so SystemCertPool validates it","Test basic reachability outside the app (openssl s_client, curl, nc) to isolate TLS vs network vs DNS","Retry with backoff for transient outages; the fixed 30s WithBlock window is not tunable by callers"],"exampleFix":"// before\nconn, err := grpc.CreateConnection(ctx, addr, true, \"/management\")\nif err != nil { return err }\n\n// after\nconn, err := grpc.CreateConnection(ctx, addr, true, \"/management\")\nif err != nil {\n    if errors.Is(err, context.DeadlineExceeded) {\n        return fmt.Errorf(\"management unreachable at %s: %w\", addr, err)\n    }\n    return fmt.Errorf(\"connect management: %w\", err)\n}","handlingStrategy":"retry","validationCode":"// preflight outside the app before dialing\n// nc -vz host 443  /  openssl s_client -connect host:443\nu, err := url.Parse(addr)\nif err != nil || u.Host == \"\" {\n    return fmt.Errorf(\"invalid service address %q\", addr)\n}","typeGuard":"func reachableAddr(addr string) bool {\n    u, err := url.Parse(addr)\n    return err == nil && u.Host != \"\" && u.Port() != \"\"\n}","tryCatchPattern":"var conn *grpc.ClientConn\nerr := backoff.Retry(func() error {\n    c, e := grpc.CreateConnection(ctx, addr, tlsEnabled, \"/management\")\n    if e != nil {\n        if errors.Is(e, context.DeadlineExceeded) || isTemporary(e) {\n            return e // retry with backoff\n        }\n        return backoff.Permanent(e) // TLS trust / config: fix, don't retry\n    }\n    conn = c\n    return nil\n}, grpc.Backoff(ctx))","preventionTips":["Install the server CA into the OS trust store or serve a publicly trusted certificate","Validate the management/signal URL shape before first connect","Distinguish permanent causes (x509, refused) from transient (deadline) and only retry the latter","Monitor dial failures: persistent DeadlineExceeded usually means a firewall or DNS problem, not slowness"],"tags":["go","netbird","grpc","tls","network","timeout"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}