slackhq/nebula · error
%s rule #%v; only one of port or code should be provided
Error message
%s rule #%v; only one of port or code should be provided
What it means
A firewall rule may specify a port (for tcp/udp) or a code (for icmp), but not both. AddFirewallRulesFromConfig rejects rules where both Code and Port are non-empty so the resulting rule is unambiguous.
Source
Thrown at firewall.go:345
r := c.Get(table)
if r == nil {
return nil
}
rs, ok := r.([]any)
if !ok {
return fmt.Errorf("%s failed to parse, should be an array of rules", table)
}
for i, t := range rs {
r, err := convertRule(l, t, table, i)
if err != nil {
return fmt.Errorf("%s rule #%v; %s", table, i, err)
}
if r.Code != "" && r.Port != "" {
return fmt.Errorf("%s rule #%v; only one of port or code should be provided", table, i)
}
if r.Host == "" && len(r.Groups) == 0 && r.Cidr == "" && r.LocalCidr == "" && r.CAName == "" && r.CASha == "" {
return fmt.Errorf("%s rule #%v; at least one of host, group, cidr, local_cidr, ca_name, or ca_sha must be provided", table, i)
}
var sPort, errPort string
if r.Code != "" {
errPort = "code"
sPort = r.Code
} else {
errPort = "port"
sPort = r.Port
}
var proto uint8
var startPort, endPort int32
switch r.Proto {View on GitHub (pinned to dd8f660c0a)
Solutions
- Remove the "port" field if the rule is an ICMP rule identified by "code".
- Remove the "code" field if the rule is tcp/udp identified by "port".
- Split into two rules if you genuinely need both a port-based and a code-based rule.
Example fix
// before (config) - port: 443 code: 8 proto: tcp // after - port: 443 proto: tcp
Defensive patterns
Strategy: validation
Validate before calling
func checkPortXorCode(rule map[string]any, table string, i int) error {
_, hasPort := rule["port"]
_, hasCode := rule["code"]
if hasPort && hasCode {
return fmt.Errorf("%s rule #%d: only one of port or code", table, i)
}
return nil
} Try / catch
if err := fw.AddFirewallRulesFromConfig(l, table, rules); err != nil {
if strings.Contains(err.Error(), "only one of port or code") {
log.Fatalf("fix rule: keep port for tcp/udp, code for icmp: %v", err)
}
return err
} Prevention
- Use distinct rule templates for tcp/udp (port) and icmp (code) rules.
- When editing rules by hand, delete the unused field, don't just comment it out in generated YAML.
- Lint firewall rules for mutually exclusive fields in CI.
When it happens
Trigger: A rule in inbound/outbound that sets both "port" and "code" fields, e.g. {port: "443", code: "8", proto: icmp}.
Common situations: Copy-pasting a rule template and forgetting to delete the unused port/code field, or merging rules from different examples.
Related errors
- unknown protocol %v
- %s failed to parse, should be an array of rules
- %s rule #%v; at least one of host, group, cidr, local_cidr,
- %s rule #%v; proto was not understood; `%s`
- ErrInvalidLocalIP
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/1f024441f6ce0299.
Report an issue: GitHub.