OpenNHP/opennhp · error
cluster instance # : must set either Host or Ip
Error message
cluster %q instance #%d: must set either Host or Ip
What it means
buildCluster validates each [[Servers]] instance entry in server.toml before creating a UdpPeer. When an instance defines neither Host nor Ip, there is no address to knock against, so the cluster cannot be built and a descriptive error naming the cluster and instance index is returned. This is a config-validation guard to fail fast at startup instead of producing an unresolvable peer.
Solutions
- Set either Host (DNS name) or Ip for every instance in the cluster's [[Servers.Instances]] in server.toml.
- Check the rendered config in deploy/configs/ or /etc/opennhp/agent to confirm the address variable (e.g. ${NHP_SERVER_HOST}) was not empty at render time.
- If building the Config in code, populate ic.Host or ic.Ip before calling buildCluster.
- Run the agent once with debug logging to see which cluster name and instance index failed, then fix that block.
Example fix
// before [[Servers.Instances]] Port = 10581 PubKeyBase64 = "..." // after [[Servers.Instances]] Ip = "10.0.0.5" # or Host = "nhp.example.org" Port = 10581 PubKeyBase64 = "..."
Defensive patterns
Strategy: validation
Validate before calling
for i, ic := range cfg.Instances {
if ic.Host == "" && ic.Ip == "" {
return fmt.Errorf("instance %d of cluster %q needs Host or Ip", i, cfg.Name)
}
} Try / catch
clusters, err := buildCluster(cfg)
if err != nil {
return fmt.Errorf("load server.toml: %w", err)
} Prevention
- Lint server.toml at deploy time: every instance must have Host or Ip.
- Check rendered templates for empty envsubst variables before shipping configs.
- Add a unit test covering an instance with both fields empty.
When it happens
Trigger: Calling buildCluster (directly or via buildTwoInstanceCluster, updateServerPeers, or FindServerClusterFromResource paths in tests) with a cfg.Instances[i] where both Host=="" and Ip=="".
Common situations: Hand-edited server.toml where a [[Servers.Instances]] block has a Port and PubKey but the Host/Ip line was deleted or commented out; template rendering with envsubst where the address variable was empty in the secrets/config template; programmatic Config construction in tests omitting both fields.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- cluster instance # : invalid port
- unknown remote provider
- unknown remote provider
- key not found
- value not set
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/c1d11bcb8697890e.
Report an issue: GitHub.
Appendix: source
Thrown at endpoints/agent/cluster.go:155
cfg.Name, cfg.PubKeyBase64)
}
if err := cfg.LoadBalance.Validate(); err != nil {
return nil, fmt.Errorf("cluster %q (%s): %w",
cfg.Name, cfg.PubKeyBase64, err)
}
sc := &ServerCluster{
PublicKeyBase64: cfg.PubKeyBase64,
Name: cfg.Name,
Sticky: cfg.StickyOrDefault(),
instances: make([]*ServerInstance, 0, len(cfg.Instances)),
}
for i, ic := range cfg.Instances {
host := ic.Host
ip := ic.Ip
if host == "" && ip == "" {
return nil, fmt.Errorf("cluster %q instance #%d: must set either Host or Ip",
cfg.Name, i)
}
if ic.Port <= 0 {
return nil, fmt.Errorf("cluster %q instance #%d: invalid port %d",
cfg.Name, i, ic.Port)
}
peer := &core.UdpPeer{
PubKeyBase64: cfg.PubKeyBase64,
Hostname: host,
Ip: ip,
Port: ic.Port,
Type: core.NHP_SERVER,
ExpireTime: cfg.ExpireTime,
}
displayHost := host
if displayHost == "" {
displayHost = ip
}View on GitHub (pinned to 6e04ca5ff0)