OpenNHP/opennhp · error
: [[Servers]][ ] ( ) sets both top-level Ip/Hostname/Port…
Error message
%s: [[Servers]][%d] (%s) sets both top-level Ip/Hostname/Port and [[Servers.Instances]]; pick one form — top-level fields are deprecated, prefer Instances
What it means
Cluster-config validation error from Normalize: one [[Servers]] entry declares both the deprecated top-level Ip/Hostname/Port fields and a [[Servers.Instances]] sub-table. This almost always indicates an incomplete migration, and the loader refuses to guess which form the operator meant, so it rejects the entry instead of silently picking one address set.
Solutions
- Delete the deprecated top-level Ip/Hostname/Port fields from the entry
- Keep the [[Servers.Instances]] block as the single source of addresses
- Repeat for every entry flagged by the error
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at nhp/common/clusterconfig/clusterconfig.go:172 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/5beab234e70c600b.
Report an issue: GitHub.
Appendix: source
Thrown at nhp/common/clusterconfig/clusterconfig.go:172
if len(c.Name) > NameMaxLen {
return fmt.Errorf("%s: [[Servers]][%d] Name %q exceeds %d chars",
label, i, c.Name, NameMaxLen)
}
if !clusterNameRegex.MatchString(c.Name) {
return fmt.Errorf("%s: [[Servers]][%d] Name %q invalid — allowed chars: [a-zA-Z0-9._-]",
label, i, c.Name)
}
}
legacy := c.hasLegacyFields()
hasInstances := len(c.Instances) > 0
switch {
case legacy && hasInstances:
// Both forms in one entry is almost certainly an
// incomplete migration. Refuse to guess which one the
// operator meant.
return fmt.Errorf("%s: [[Servers]][%d] (%s) sets both top-level Ip/Hostname/Port and [[Servers.Instances]]; "+
"pick one form — top-level fields are deprecated, prefer Instances",
label, i, c.PubKeyBase64)
case legacy && !hasInstances:
deprecate("%s: [[Servers]][%d] uses legacy single-server form (Hostname/Ip/Port at top level); "+
"migrate to [[Servers.Instances]] in server.toml — auto-upgrading for now",
label, i)
c.Instances = []InstanceConfig{{
Host: c.Hostname,
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)
}
View on GitHub (pinned to 6e04ca5ff0)