lima-vm/lima · error

field `%s.hostPort` must match field `%s.hostPortRange[0]`

Error message

field `%s.hostPort` must match field `%s.hostPortRange[0]`

What it means

The validator requires that when a portForward rule specifies an explicit HostPort, it equals HostPortRange[0]. HostPort is a convenience duplicate of the range start; if they disagree the rule is internally inconsistent. This catches rules where the scalar and range forms were edited independently.

Source

Thrown at pkg/limayaml/validate.go:329

		}
		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)
				}
			}
		}
		if rule.GuestPortRange[0] > rule.GuestPortRange[1] {
			errs = errors.Join(errs, fmt.Errorf("field `%s.guestPortRange[1]` must be greater than or equal to field `%s.guestPortRange[0]`", field, field))

View on GitHub (pinned to dd909d0973)

Solutions

  1. Set hostPort equal to the first element of hostPortRange
  2. Or drop hostPort entirely and rely on hostPortRange alone
  3. Or drop hostPortRange and express a single port with hostPort plus a matching hostPortRange [n, n]

Example fix

// before
portForwards:
  - guestPort: 80
    hostPort: 8080
    hostPortRange: [9090, 9091]
// after
portForwards:
  - guestPort: 80
    hostPort: 8080
    hostPortRange: [8080, 8080]
Defensive patterns

Strategy: validation

Validate before calling

for i, rule := range y.PortForwards {
  if rule.HostPort != 0 && rule.HostPort != rule.HostPortRange[0] {
    return fmt.Errorf("portForwards[%d]: hostPort must equal hostPortRange[0]", i)
  }
}

Type guard

func hostPortConsistent(rule limatype.PortForward) bool { return rule.HostPort == 0 || rule.HostPort == rule.HostPortRange[0] }

Try / catch

if err := limayaml.Validate(y, false); err != nil {
  if strings.Contains(err.Error(), "must match field") && strings.Contains(err.Error(), "hostPortRange[0]") {
    // sync hostPort with hostPortRange[0]
  }
}

Prevention

When it happens

Trigger: Validate on a LimaYAML where portForwards[i].HostPort != 0 and HostPort != HostPortRange[0] — e.g. hostPort: 8080 with hostPortRange: [9090, 9091].

Common situations: Changing hostPortRange but forgetting the standalone hostPort field; generating YAML programmatically where the range is computed but the scalar copied from an old value; typos in one of the two fields.

Related errors


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