derailed/k9s · error
kubectl command must not be in the current working directory
Error message
kubectl command must not be in the current working directory: %w
What it means
runK() resolves kubectl with exec.LookPath. Since Go 1.19, LookPath returns the sentinel error exec.ErrDot when the resolved binary is a relative path — i.e. kubectl was found in the current working directory (./kubectl), which Go refuses to use implicitly for security (a hostile writable directory could hijack command resolution). k9s surfaces this explicitly instead of silently running the local binary.
Solutions
- Install kubectl into a real PATH directory (e.g. /usr/local/bin/kubectl) so it resolves absolutely
- Remove or rename the ./kubectl in your working directory before launching k9s
- Launch k9s from a directory that does not contain a kubectl binary
Example fix
# before — running k9s from a dir containing ./kubectl $ cd ~/project && ls kubectl $ k9s # any kubectl-backed feature fails with ErrDot # after $ sudo mv ~/project/kubectl /usr/local/bin/kubectl $ k9s # resolves via PATH, works
Defensive patterns
Strategy: validation
Validate before calling
// preflight: resolve kubectl and refuse cwd-relative hits before running
bin, err := exec.LookPath("kubectl")
if errors.Is(err, exec.ErrDot) {
return fmt.Errorf("refusing ./kubectl — install kubectl on PATH")
}
if path.IsAbs(bin) { /* safe to proceed */ } Prevention
- Never keep a kubectl binary in directories you launch k9s from
- Install kubectl under /usr/local/bin or ~/.local/bin listed early in PATH
- Treat exec.ErrDot as a security signal — a writable-dir binary hijack, not an inconvenience
When it happens
Trigger: Starting k9s in a directory that contains a kubectl executable and no earlier PATH entry wins — e.g. you downloaded kubectl into a project folder and launch k9s from there, invoking any kubectl-shelling feature (shell, port-forward helpers, kubectl prompts).
Common situations: Per-project kubectl binaries (version managers that drop kubectl into ./bin with PATH=.:/bin styles); CI scripts that cd into a tools directory; users following install docs that say 'download kubectl here' and run k9s in the same dir.
Related errors
- kubectl command is not in your path
- command failed. Check k9s logs
- expected Unstructured, but got %T
- shell exec failed
- data section in secret description is invalid
AI-assisted analysis of derailed/k9s@2d3ccc6ba2 (2026-08-15).
Data as JSON: /api/errors/4af179fbd7d2ca9d.
Report an issue: GitHub.
Appendix: source
Thrown at internal/view/exec.go:61
var editorEnvVars = []string{"K9S_EDITOR", "KUBE_EDITOR", "EDITOR"}
type shellOpts struct {
clear, background bool
pipes []string
binary string
banner string
args []string
}
func (s shellOpts) String() string {
return fmt.Sprintf("%s %s", s.binary, strings.Join(s.args, " "))
}
func runK(a *App, opts *shellOpts) error {
bin, err := exec.LookPath("kubectl")
if errors.Is(err, exec.ErrDot) {
return fmt.Errorf("kubectl command must not be in the current working directory: %w", err)
}
if err != nil {
return fmt.Errorf("kubectl command is not in your path: %w", err)
}
args := []string{opts.args[0]}
if u, err := a.Conn().Config().ImpersonateUser(); err == nil {
args = append(args, "--as", u)
}
if g, err := a.Conn().Config().ImpersonateGroups(); err == nil {
args = append(args, "--as-group", g)
}
if isInsecure := a.Conn().Config().Flags().Insecure; isInsecure != nil && *isInsecure {
args = append(args, "--insecure-skip-tls-verify")
}
args = append(args, "--context", a.Config.K9s.ActiveContextName())
if cfg := a.Conn().Config().Flags().KubeConfig; cfg != nil && *cfg != "" {
args = append(args, "--kubeconfig", *cfg)
}View on GitHub (pinned to 2d3ccc6ba2)