lima-vm/lima · error

field `%s.hostPort` must be 0 when field `%s.hostSocket` is

Error message

field `%s.hostPort` must be 0 when field `%s.hostSocket` is set

What it means

Lima's limayaml validator rejects a portForward rule that sets both a numeric hostPort and a hostSocket. A rule may forward to either a TCP/UDP port or a Unix socket on the host, never both at once. The conflict is detected inside Validate() while checking every entry of the portForwards array.

Source

Thrown at pkg/limayaml/validate.go:326

		field := fmt.Sprintf("portForwards[%d]", i)
		if *rule.GuestIPMustBeZero && !rule.GuestIP.Equal(net.IPv4zero) {
			errs = errors.Join(errs, fmt.Errorf("field `%s.guestIPMustBeZero` can only be true when field `%s.guestIP` is 0.0.0.0", field, field))
		}
		if rule.GuestPort != 0 {
			if rule.GuestSocket != "" {
				errs = errors.Join(errs, fmt.Errorf("field `%s.guestPort` must be 0 when field `%s.guestSocket` is set", field, field))
			}
			if rule.GuestPort != rule.GuestPortRange[0] {
				errs = errors.Join(errs, fmt.Errorf("field `%s.guestPort` must match field `%s.guestPortRange[0]`", field, field))
			}
			// redundant validation to make sure the error contains the correct field name
			if err := validatePort(field+".guestPort", rule.GuestPort); err != nil {
				errs = errors.Join(errs, err)
			}
		}
		if rule.HostPort != 0 {
			if rule.HostSocket != "" {
				errs = errors.Join(errs, fmt.Errorf("field `%s.hostPort` must be 0 when field `%s.hostSocket` is set", field, field))
			}
			if rule.HostPort != rule.HostPortRange[0] {
				errs = errors.Join(errs, fmt.Errorf("field `%s.hostPort` must match field `%s.hostPortRange[0]`", field, field))
			}
			// redundant validation to make sure the error contains the correct field name
			if err := validatePort(field+".hostPort", rule.HostPort); err != nil {
				errs = errors.Join(errs, err)
			}
		}
		for j := range 2 {
			if err := validatePort(fmt.Sprintf("%s.guestPortRange[%d]", field, j), rule.GuestPortRange[j]); err != nil {
				errs = errors.Join(errs, err)
			}
			if rule.HostSocket == "" {
				if err := validatePort(fmt.Sprintf("%s.hostPortRange[%d]", field, j), rule.HostPortRange[j]); err != nil {
					errs = errors.Join(errs, err)
				}
			}

View on GitHub (pinned to dd909d0973)

Solutions

  1. Remove the hostPort field from the rule, keeping hostSocket
  2. Or remove hostSocket and keep hostPort (with a matching hostPortRange)
  3. Run `limactl template validate` after editing to confirm the rule is now unambiguous

Example fix

// before
portForwards:
  - guestPort: 80
    hostPort: 8080
    hostSocket: /tmp/web.sock
// after
portForwards:
  - guestPort: 80
    hostSocket: /tmp/web.sock
Defensive patterns

Strategy: validation

Validate before calling

for i, rule := range y.PortForwards {
  if rule.HostPort != 0 && rule.HostSocket != "" {
    return fmt.Errorf("portForwards[%d]: set either hostPort or hostSocket, not both", i)
  }
}

Type guard

func ruleUsesPort(rule limatype.PortForward) bool { return rule.HostPort != 0 && rule.HostSocket == "" }

Try / catch

if err := limayaml.Validate(y, false); err != nil {
  if strings.Contains(err.Error(), "hostPort` must be 0 when") {
    // fix rule: drop hostPort where hostSocket is set
  }
}

Prevention

When it happens

Trigger: Calling Validate (via limactl start/edit/restart, limactl template validate, limactl edit --yq, or templateArgs resolution) on a LimaYAML where some portForwards[i] has HostPort != 0 AND HostSocket != "".

Common situations: Hand-editing a portForward rule to switch from port to socket forwarding while leaving the old hostPort value in place; merging YAML fragments from two templates; scripted yq edits that set hostSocket without clearing hostPort.

Related errors


AI-assisted analysis of lima-vm/lima@dd909d0973 (2026-09-01). Data as JSON: /api/errors/2966641ad58f0f26. Report an issue: GitHub.