netbirdio/netbird · error

readiness check: unexpected daemon status %q

Error message

readiness check: unexpected daemon status %q

What it means

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.

Source

Thrown at client/cmd/status.go:286

		return nil
	case "ready":
		return checkReadiness(resp)
	case "startup":
		return checkStartup(resp)
	default:
		return nil
	}
}

func checkReadiness(resp *proto.StatusResponse) error {
	daemonStatus := internal.StatusType(resp.GetStatus())
	switch daemonStatus {
	case internal.StatusIdle, internal.StatusConnecting, internal.StatusConnected:
		return nil
	case internal.StatusNeedsLogin, internal.StatusLoginFailed, internal.StatusSessionExpired:
		return fmt.Errorf("readiness check: daemon status is %s", daemonStatus)
	default:
		return fmt.Errorf("readiness check: unexpected daemon status %q", daemonStatus)
	}
}

func checkStartup(resp *proto.StatusResponse) error {
	fullStatus := resp.GetFullStatus()
	if fullStatus == nil {
		return fmt.Errorf("startup check: no full status available")
	}

	if !fullStatus.GetManagementState().GetConnected() {
		return fmt.Errorf("startup check: management not connected")
	}

	if !fullStatus.GetSignalState().GetConnected() {
		return fmt.Errorf("startup check: signal not connected")
	}

	var relayCount, relaysConnected int

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Align CLI and daemon to the same release: reinstall both (e.g. 'netbird service install' with the new binary, then restart the service)
  2. Retry the check after a few seconds - the daemon sets a real status once the engine initializes
  3. Inspect the raw value with 'netbird status -A' (or daemon logs) to see exactly what status string was returned
  4. If you build from source and added a StatusType, extend the switch in checkReadiness to handle it

Example fix

// before
default:
    return fmt.Errorf("readiness check: unexpected daemon status %q", daemonStatus)

// after: distinguish not-yet-started from truly unknown
case internal.StatusType(""):
    return fmt.Errorf("readiness check: daemon has not reported a status yet")
default:
    return fmt.Errorf("readiness check: unexpected daemon status %q (check CLI/daemon version match)", daemonStatus)
Defensive patterns

Strategy: validation

Validate before calling

// probe before treating the check result as meaningful
conn, err := DialClientGRPCServer(ctx, daemonAddr)
if err != nil {
    // daemon down: not a status problem, fail separately
}
resp, err := proto.NewDaemonServiceClient(conn).Status(ctx, &proto.StatusRequest{})
if err == nil && resp.GetStatus() == "" {
    // daemon has not initialized: retry later instead of reading it as 'unexpected'
}

Type guard

func isKnownDaemonStatus(s string) bool {
    switch internal.StatusType(s) {
    case internal.StatusIdle, internal.StatusConnecting, internal.StatusConnected,
        internal.StatusNeedsLogin, internal.StatusLoginFailed, internal.StatusSessionExpired:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/acace686b82ffed3. Report an issue: GitHub.