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

  1. Remove the "port" field if the rule is an ICMP rule identified by "code".
  2. Remove the "code" field if the rule is tcp/udp identified by "port".
  3. 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

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


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/1f024441f6ce0299. Report an issue: GitHub.