{"record":{"id":"bbb3d63ce20dec2f","repo":"netbirdio/netbird","slug":"client-not-started","errorCode":null,"errorMessage":"client not started","messagePattern":"client not started","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/embed/embed.go","lineNumber":33,"sourceCode":"\twgdevice \"golang.zx2c4.com/wireguard/device\"\n\twgnetstack \"golang.zx2c4.com/wireguard/tun/netstack\"\n\n\t\"github.com/netbirdio/netbird/client/iface\"\n\t\"github.com/netbirdio/netbird/client/iface/netstack\"\n\t\"github.com/netbirdio/netbird/client/internal\"\n\t\"github.com/netbirdio/netbird/client/internal/auth\"\n\t\"github.com/netbirdio/netbird/client/internal/peer\"\n\t\"github.com/netbirdio/netbird/client/internal/profilemanager\"\n\tsshcommon \"github.com/netbirdio/netbird/client/ssh\"\n\t\"github.com/netbirdio/netbird/client/system\"\n\t\"github.com/netbirdio/netbird/shared/management/domain\"\n\tmgmProto \"github.com/netbirdio/netbird/shared/management/proto\"\n\t\"github.com/netbirdio/netbird/util/capture\"\n)\n\nvar (\n\tErrClientAlreadyStarted = errors.New(\"client already started\")\n\tErrClientNotStarted     = errors.New(\"client not started\")\n\tErrEngineNotStarted     = errors.New(\"engine not started\")\n\tErrConfigNotInitialized = errors.New(\"config not initialized\")\n)\n\nconst (\n\t// PeerStatusConnected indicates the peer is in connected state.\n\tPeerStatusConnected = peer.StatusConnected\n)\n\n// PeerConnStatus is a peer's connection status.\ntype PeerConnStatus = peer.ConnStatus\n\n// Client manages a netbird embedded client instance.\ntype Client struct {\n\tdeviceName string\n\tconfig     *profilemanager.Config\n\tmu         sync.Mutex\n\tcancel     context.CancelFunc","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/embed/embed.go#L15-L51","documentation":"Same call site as index 6 (middleware.go:472) but for the errValidationUnavailable branch: 502 'authentication service unavailable'. validateSessionToken wraps this sentinel (middleware.go:698) when an OIDC method token must be checked via the sessionValidator gRPC client (ValidateSession on management) and that RPC itself errors.","triggerScenarios":"Request presents a header token for a domain whose scheme is OIDC, mw.sessionValidator is wired, and the gRPC call to management's ValidateSession fails: management down or restarting, gRPC connection refused/timeout, TLS handshake failure between proxy and management, or management returning an error status.","commonSituations":"Management service restarted and the proxy's gRPC connection has not recovered; mTLS/cert mismatch between proxy and management after certificate renewal; management pod evicted or crashing; network policy blocking the proxy-to-management port.","solutions":["Check management health and connectivity from the proxy host (the gRPC endpoint the sessionValidator dials).","Look at proxy logs: the underlying error is chained after 'session validation unavailable', naming dial timeout, TLS, or unavailable status.","Restart or re-dial the gRPC connection / proxy process if the channel is wedged after a management restart.","Verify mTLS material between proxy and management is current on both sides."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Pre-flight the proxy->management validation path before relying on it.\nconn, err := grpc.NewClient(mgmtAddr, creds)\nif err != nil {\n    return fmt.Errorf(\"management dial: %w\", err)\n}\ndefer conn.Close()\nc := healthpb.NewHealthClient(conn)\nctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)\ndefer cancel()\nif _, err := c.Check(ctx, &healthpb.HealthCheckRequest{}); err != nil {\n    return fmt.Errorf(\"management unhealthy: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"// With retry (502 means the backend, not the credentials, failed):\nvar resp *http.Response\nfor attempt := 0; attempt < 3; attempt++ {\n    resp, err = client.Do(req.Clone(ctx))\n    if err == nil && resp.StatusCode != http.StatusBadGateway {\n        break\n    }\n    time.Sleep(time.Duration(1<<attempt) * time.Second) // backoff; mgmt may be restarting\n}","preventionTips":["Keep management highly available or at least monitored; this 502 is the proxied form of its outage.","Verify mTLS material between proxy and management after every certificate rotation.","Alert on 'authentication service unavailable' responses — they indicate proxy-management split, not user error.","Retry with backoff; a single failed ValidateSession is transient, credentials do not need refreshing."],"tags":["proxy","grpc","session-validation","availability","oidc"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}