OpenNHP/opennhp · error
: [[Servers]][ ] instance # : Host and Ip both empty
Error message
%s: [[Servers]][%d] instance #%d: Host and Ip both empty
What it means
Cluster-config validation error from Normalize while iterating a server's Instances: an instance declares neither Host nor Ip, so there is no address to dial. The instance index and server entry are included in the message to locate the empty block in server.toml.
Solutions
- Set Host (FQDN) or Ip on the flagged [[Servers.Instances]] entry
- Remove the instance block entirely if the endpoint is no longer used
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at nhp/common/clusterconfig/clusterconfig.go:199 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07).
Data as JSON: /api/errors/ad8b79a46d5a7eb4.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/common/clusterconfig/clusterconfig.go:199
Ip: c.Ip,
Port: c.Port,
Weight: 1,
}}
// Zero the legacy fields so downstream code never sees both.
c.Hostname, c.Ip, c.Port = "", "", 0
case !legacy && !hasInstances:
return fmt.Errorf("%s: [[Servers]][%d] (%s) has no instances", label, i, c.PubKeyBase64)
}
if err := c.LoadBalance.Validate(); err != nil {
return fmt.Errorf("%s: [[Servers]][%d] (%s): %w", label, i, c.PubKeyBase64, err)
}
c.LoadBalance = c.LoadBalance.Normalize()
for j := range c.Instances {
inst := &c.Instances[j]
if inst.Host == "" && inst.Ip == "" {
return fmt.Errorf("%s: [[Servers]][%d] instance #%d: Host and Ip both empty", label, i, j)
}
if inst.Port <= 0 {
return fmt.Errorf("%s: [[Servers]][%d] instance #%d: invalid Port %d", label, i, j, inst.Port)
}
if inst.Weight <= 0 {
inst.Weight = 1
}
}
}
// Duplicate pubkey detection — two clusters with the same pubkey
// would race for the same slot in device.peerMap. Catch it here
// so the error is obvious at load rather than as a mysterious
// "wrong instance answered" at runtime.
seenPK := make(map[string]int, len(clusters))
for i, c := range clusters {
if prev, ok := seenPK[c.PubKeyBase64]; ok {
return fmt.Errorf("%s: [[Servers]][%d] and [[Servers]][%d] share PubKeyBase64 %s — "+View on GitHub (pinned to 6e04ca5ff0)