{"record":{"id":"c4bc264a25617be2","repo":"netbirdio/netbird","slug":"client-not-initialized","errorCode":null,"errorMessage":"client not initialized","messagePattern":"client not initialized","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/server/server.go","lineNumber":1630,"sourceCode":"\treturn sshServerState\n}\n\n// GetPeerSSHHostKey retrieves SSH host key for a specific peer\nfunc (s *Server) GetPeerSSHHostKey(\n\tctx context.Context,\n\treq *proto.GetPeerSSHHostKeyRequest,\n) (*proto.GetPeerSSHHostKeyResponse, error) {\n\tif ctx.Err() != nil {\n\t\treturn nil, ctx.Err()\n\t}\n\n\ts.mutex.Lock()\n\tconnectClient := s.connectClient\n\tstatusRecorder := s.statusRecorder\n\ts.mutex.Unlock()\n\n\tif connectClient == nil {\n\t\treturn nil, errors.New(\"client not initialized\")\n\t}\n\n\tengine := connectClient.Engine()\n\tif engine == nil {\n\t\treturn nil, errors.New(\"engine not started\")\n\t}\n\n\tpeerAddress := req.GetPeerAddress()\n\thostKey, found := engine.GetPeerSSHKey(peerAddress)\n\n\tresponse := &proto.GetPeerSSHHostKeyResponse{\n\t\tFound: found,\n\t}\n\n\tif !found {\n\t\treturn response, nil\n\t}\n","sourceCodeStart":1612,"sourceCodeEnd":1648,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/server/server.go#L1612-L1648","documentation":"Returned by the daemon's GetPeerSSHHostKey RPC handler (client/server/server.go:1630) when s.connectClient is nil. The connect client is created when the daemon establishes its session (login/up); nil means the daemon is not initialized (no session), so there is no engine to query for peer SSH host keys.","triggerScenarios":"Calling GetPeerSSHHostKey on a daemon that has not logged in / connected yet, or after logout tore the connect client down; a UI restart racing the first connect.","commonSituations":"SSH config helper (netbird's ssh shim) invoked before netbird up completes; scripts calling the daemon gRPC socket directly at boot; running the SSH command after logout.","solutions":["Wait for the daemon status to reach Connected before using SSH features that need host-key lookup.","If persistent, run netbird up / login to (re)initialize the client.","Callers (e.g. the SSH ProxyCommand) should degrade gracefully: prompt the user instead of failing hard."],"exampleFix":"// before\nresp, err := daemonClient.GetPeerSSHHostKey(ctx, req)\nif err != nil { exit(1) } // \"client not initialized\" at boot\n\n// after: gate on session state\nstatus, _ := daemonClient.Status(ctx)\nif status.GetStatus() != daemonpb.StatusEnum_CONNECTED {\n    return fmt.Errorf(\"daemon not connected yet; retry SSH later\")\n}\nresp, err := daemonClient.GetPeerSSHHostKey(ctx, req)","handlingStrategy":"validation","validationCode":"// Require a connected daemon before any SSH host-key lookup.\nstatus, err := daemonClient.Status(ctx)\nif err != nil {\n    return err\n}\nif status.GetStatus() != daemonpb.StatusEnum_CONNECTED {\n    return fmt.Errorf(\"daemon has no session (status %s); run up/login first\", status.GetStatus())\n}","typeGuard":null,"tryCatchPattern":"resp, err := daemonClient.GetPeerSSHHostKey(ctx, req)\nif err != nil {\n    if strings.Contains(err.Error(), \"client not initialized\") {\n        // daemon not logged in: prompt user to connect, then retry\n    }\n    return err\n}","preventionTips":["SSH helpers invoked from ssh_config should tolerate a not-yet-initialized daemon.","In boot-time scripts, wait for the daemon socket plus Connected status before SSH use."],"tags":["go","netbird","daemon","ssh","rpc","lifecycle"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}