derailed/k9s · error
no exposed ports
Error message
no exposed ports
What it means
Annotations.PreferredPorts decides which container port to port-forward: with no k9s.io/portforward annotation it defaults to the first declared container port. If the container spec declares zero ports (specs is empty) there is nothing to forward and k9s refuses rather than guessing. Only an explicit annotation with an explicit port can override this.
Source
Thrown at internal/port/ann.go:14
// SPDX-License-Identifier: Apache-2.0
// Copyright Authors of K9s
package port
import (
"errors"
)
type Annotations map[string]string
func (a Annotations) PreferredPorts(specs ContainerPortSpecs) (PFAnns, error) {
if len(specs) == 0 {
return nil, errors.New("no exposed ports")
}
value, ok := a[K9sPortForwardsKey]
if !ok {
return PFAnns{specs[0].ToPFAnn()}, nil
}
return specs.MatchAnnotations(value), nil
}
View on GitHub (pinned to 2d3ccc6ba2)
Solutions
- Annotate the pod to declare the port explicitly: kubectl annotate pod <p> k9s.io/portforward="container::localPort:containerPort" so PreferredPorts uses MatchAnnotations instead of the empty spec list.
- Or add containerPort entries to the workload spec if you own it.
- Port-forward via the Service instead, where targetPort mapping is known.
Example fix
# before: container has no ports -> "no exposed ports"
spec:
containers:
- name: app
image: app:dev
# after: declare the listening port
spec:
containers:
- name: app
image: app:dev
ports:
- containerPort: 8080 Defensive patterns
Strategy: validation
Validate before calling
if len(specs) == 0 {
// cannot pick a default port; require an explicit annotation
if ann, ok := podAnns[port.K9sPortForwardsKey]; ok {
_ = ann // use annotation path
} else {
return errors.New("container exposes no ports; annotate or add containerPort")
}
} Type guard
func hasExposedPorts(specs port.ContainerPortSpecs) bool { return len(specs) > 0 } Prevention
- Declare containerPort for anything you intend to port-forward.
- Annotate pods with k9s.io/portforward when ports are dynamic.
- Port-forward via the Service when the pod exposes nothing.
When it happens
Trigger: Launching a port-forward on a pod whose container spec has no ports[] entries and no k9s port-forward annotation; containers that receive traffic only via Service port targeting or env-configured listeners.
Common situations: Port-forwarding helper/sidecar containers (e.g. log shippers) with no declared ports; apps where the Dockerfile EXPOSE was not translated into containerPort; Istio-injected proxies in the list.
Related errors
- no port number assigned
- revision conversion failed
- invalid annotation %q
- invalid plain port-forward %s
- invalid port-forward specification %s
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/cdaacd4a80e50363.
Report an issue: GitHub.