derailed/k9s · warning

container to local port mismatch

Error message

container to local port mismatch

What it means

Thrown by the k9s port-forward dialog's OK handler when either the Container Port or Local Port input field is left empty. Despite the wording 'mismatch', the check in internal/view/pf_dialog.go:74 only compares the two fields to the empty string — no actual comparison between container and local port is performed. The message is therefore misleading: it fires on blank input, not on a real mismatch.

Source

Thrown at internal/view/pf_dialog.go:75

		p2 = p
	})
	if loField.GetText() == "" {
		loField.SetPlaceholder("Enter a local port")
	}
	address := v.App().Config.K9s.PortForwardAddress
	f.AddInputField("Address:", address, fieldLen, nil, func(h string) {
		address = h
	})
	for i := range 3 {
		if field, ok := f.GetFormItem(i).(*tview.InputField); ok {
			field.SetLabelColor(styles.LabelFgColor.Color())
			field.SetFieldTextColor(styles.FieldFgColor.Color())
		}
	}

	f.AddButton("OK", func() {
		if coField.GetText() == "" || loField.GetText() == "" {
			v.App().Flash().Err(fmt.Errorf("container to local port mismatch"))
			return
		}
		tt, err := port.ToTunnels(address, coField.GetText(), loField.GetText())
		if err != nil {
			v.App().Flash().Err(err)
			return
		}
		if err := okFn(v, path, tt); err != nil {
			v.App().Flash().Err(err)
		}
	})
	pages := v.App().Content.Pages
	f.AddButton("Cancel", func() {
		DismissPortForwards(v, pages)
	})
	for i := range 2 {
		if b := f.GetButton(i); b != nil {
			b.SetBackgroundColorActivated(styles.ButtonFocusBgColor.Color())

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Fill the Container Port field with a 'containerName::port' spec (e.g. 'web::8080') and the Local Port field with a free local port number, then press OK
  2. If unsure of the container name/port, check the pod spec (kubectl get pod <name> -o yaml | grep -A4 ports) and use that container name and containerPort
  3. Pick a local port that is not already bound (e.g. avoid ports listed by 'ss -ltn')
  4. Treat the message as 'empty port field' — if both fields are visibly filled and you still see it, report the misleading message upstream

Example fix

// before (user leaves Local Port blank and hits OK)
// -> Flash error: container to local port mismatch

// after: fill dialog fields
// Container Port: web::8080
// Local Port:    8080
// Address:       127.0.0.1
// press OK -> port.ToTunnels(address, "web::8080", "8080") succeeds
Defensive patterns

Strategy: validation

Validate before calling

// in the OK handler, validate both fields before proceeding
co, lo := strings.TrimSpace(coField.GetText()), strings.TrimSpace(loField.GetText())
if co == "" || lo == "" {
    v.App().Flash().Err(fmt.Errorf("container port and local port are both required"))
    return
}
// optional: pre-check the container::port shape
if !strings.Contains(co, "::") {
    v.App().Flash().Err(fmt.Errorf("container port must be name::port, got %q", co))
    return
}

Prevention

When it happens

Trigger: Pressing OK in the <PortForward> modal with an empty 'Container Port:' field (expected format 'containerName::port') or an empty 'Local Port:' field. Happens when the pod exposes no container ports (so no prefill via PreferredPorts/ToPortSpec) or the user clears the fields before confirming.

Common situations: Port-forwarding a pod that declares no containerPort in its spec; a dialog opened with placeholders ('Enter a container name::port', 'Enter a local port') instead of values; users who expect k9s to default the local port automatically.

Related errors


AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15). Data as JSON: /api/errors/dc7bbdfa0f36768e. Report an issue: GitHub.