{"record":{"id":"acace686b82ffed3","repo":"netbirdio/netbird","slug":"readiness-check-unexpected-daemon-status-q","errorCode":null,"errorMessage":"readiness check: unexpected daemon status %q","messagePattern":"readiness check: unexpected daemon status %q","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/cmd/status.go","lineNumber":286,"sourceCode":"\t\treturn nil\n\tcase \"ready\":\n\t\treturn checkReadiness(resp)\n\tcase \"startup\":\n\t\treturn checkStartup(resp)\n\tdefault:\n\t\treturn nil\n\t}\n}\n\nfunc checkReadiness(resp *proto.StatusResponse) error {\n\tdaemonStatus := internal.StatusType(resp.GetStatus())\n\tswitch daemonStatus {\n\tcase internal.StatusIdle, internal.StatusConnecting, internal.StatusConnected:\n\t\treturn nil\n\tcase internal.StatusNeedsLogin, internal.StatusLoginFailed, internal.StatusSessionExpired:\n\t\treturn fmt.Errorf(\"readiness check: daemon status is %s\", daemonStatus)\n\tdefault:\n\t\treturn fmt.Errorf(\"readiness check: unexpected daemon status %q\", daemonStatus)\n\t}\n}\n\nfunc checkStartup(resp *proto.StatusResponse) error {\n\tfullStatus := resp.GetFullStatus()\n\tif fullStatus == nil {\n\t\treturn fmt.Errorf(\"startup check: no full status available\")\n\t}\n\n\tif !fullStatus.GetManagementState().GetConnected() {\n\t\treturn fmt.Errorf(\"startup check: management not connected\")\n\t}\n\n\tif !fullStatus.GetSignalState().GetConnected() {\n\t\treturn fmt.Errorf(\"startup check: signal not connected\")\n\t}\n\n\tvar relayCount, relaysConnected int","sourceCodeStart":268,"sourceCodeEnd":304,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/status.go#L268-L304","documentation":"Thrown by checkReadiness (client/cmd/status.go:286), the handler behind 'netbird status --check ready'. The daemon's StatusResponse carried a status string that matches none of the six known internal.StatusType constants (idle, connecting, connected, needs_login, login_failed, session_expired), so the switch falls into default and the CLI cannot interpret the daemon's state. Almost always means CLI/daemon version skew or an empty status from a daemon that has not initialized its engine yet.","triggerScenarios":"Running 'netbird status --check ready' when resp.GetStatus() returns \"\" (daemon just started, engine not up) or a new status constant this CLI build does not know (newer daemon binary than CLI, or a custom build that added a StatusType). The switch's default branch fires and formats the raw value with %q.","commonSituations":"Upgrading the netbird CLI but not the service (or vice versa); systemd/K8s readiness probes firing before the daemon sets its first status; pinned old CLI image against an auto-updated daemon.","solutions":["Align CLI and daemon to the same release: reinstall both (e.g. 'netbird service install' with the new binary, then restart the service)","Retry the check after a few seconds - the daemon sets a real status once the engine initializes","Inspect the raw value with 'netbird status -A' (or daemon logs) to see exactly what status string was returned","If you build from source and added a StatusType, extend the switch in checkReadiness to handle it"],"exampleFix":"// before\ndefault:\n    return fmt.Errorf(\"readiness check: unexpected daemon status %q\", daemonStatus)\n\n// after: distinguish not-yet-started from truly unknown\ncase internal.StatusType(\"\"):\n    return fmt.Errorf(\"readiness check: daemon has not reported a status yet\")\ndefault:\n    return fmt.Errorf(\"readiness check: unexpected daemon status %q (check CLI/daemon version match)\", daemonStatus)","handlingStrategy":"validation","validationCode":"// probe before treating the check result as meaningful\nconn, err := DialClientGRPCServer(ctx, daemonAddr)\nif err != nil {\n    // daemon down: not a status problem, fail separately\n}\nresp, err := proto.NewDaemonServiceClient(conn).Status(ctx, &proto.StatusRequest{})\nif err == nil && resp.GetStatus() == \"\" {\n    // daemon has not initialized: retry later instead of reading it as 'unexpected'\n}","typeGuard":"func isKnownDaemonStatus(s string) bool {\n    switch internal.StatusType(s) {\n    case internal.StatusIdle, internal.StatusConnecting, internal.StatusConnected,\n        internal.StatusNeedsLogin, internal.StatusLoginFailed, internal.StatusSessionExpired:\n        return true\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Keep the CLI and the installed service on the same release version","In scripts, gate on 'netbird status --check live' before '--check ready'","Add a small retry/delay around readiness checks instead of treating a single observation as final"],"tags":["cli","daemon","readiness","version-skew","netbird"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}