ahmetb/kubectx · error

failed to listen: %w

Error message

failed to listen: %w

What it means

This error is returned by proxy.Start when net.Listen("tcp", "127.0.0.1:0") cannot open a local TCP listener. The library binds to an OS-assigned loopback port to serve the readonly reverse proxy, so failure means the process could not bind any local socket at all, not a port conflict on a specific port. The underlying net.OpError/OS error (e.g. 'too many open files', 'address family not supported') is wrapped via %w.

Source

Thrown at internal/proxy/readonly.go:85

	if err != nil {
		return nil, fmt.Errorf("failed to load kubeconfig: %w", err)
	}

	targetURL, err := url.Parse(restCfg.Host)
	if err != nil {
		return nil, fmt.Errorf("failed to parse server URL %q: %w", restCfg.Host, err)
	}

	transport, err := rest.TransportFor(restCfg)
	if err != nil {
		return nil, fmt.Errorf("failed to create transport: %w", err)
	}

	handler := NewHandler(targetURL, transport)

	listener, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return nil, fmt.Errorf("failed to listen: %w", err)
	}

	srv := &http.Server{Handler: handler}
	go srv.Serve(listener)

	debugLog.Printf("started on %s, proxying to %s", listener.Addr(), targetURL)

	return &ReadonlyProxy{
		server:   srv,
		listener: listener,
	}, nil
}

// Addr returns the listener address (e.g. "127.0.0.1:54321").
func (p *ReadonlyProxy) Addr() string {
	return p.listener.Addr().String()
}

View on GitHub (pinned to 12ad6fb22e)

Solutions

  1. Check fd exhaustion with `ulimit -n` and `lsof -p $$`; raise the limit (`ulimit -n 10240`) or close leaked descriptors/connections
  2. Verify loopback is up and usable: `ip addr show lo` / `ping -c1 127.0.0.1`, and bring it up (`ip link set lo up`) if down
  3. If in a container/sandbox, confirm the runtime allows AF_INET socket creation and loopback networking (docker run without network restrictions, adjust seccomp/AppArmor profiles)
  4. Run `KUBECTX_DEBUG=1` and read the wrapped OS error text to pinpoint EMFILE vs EADDRNOTAVAIL vs permission denied
  5. As a workaround, run kubectx outside the restricted environment (host shell) since readonly mode requires a local proxy

Example fix

// before (shell with low fd limit)
$ ulimit -n
64
// after
$ ulimit -n 10240
$ kubectx -r <ctx>
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: check loopback binding capability before calling proxy.Start
func canBindLoopback() error {
	l, err := net.Listen("tcp", "127.0.0.1:0")
	if err != nil {
		return fmt.Errorf("no loopback TCP available: %w", err)
	}
	l.Close()
	return nil
}
// also sanity-check fd headroom
func fdHeadroom() error {
	var lim syscall.Rlimit
	if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
		return err
	}
	if lim.Cur < 256 {
		return fmt.Errorf("RLIMIT_NOFILE too low: %d", lim.Cur)
	}
	return nil
}

Type guard

func isBindError(err error) bool {
	var opErr *net.OpError
	if errors.As(err, &opErr) {
		return opErr.Op == "listen"
	}
	return strings.Contains(err.Error(), "failed to listen")
}

Try / catch

p, err := proxy.Start(cfg)
if err != nil {
	if isBindError(err) {
		var sysErr *os.SyscallError
		if errors.As(err, &sysErr) && errors.Is(sysErr, syscall.EMFILE) {
			return fmt.Errorf("file descriptor limit exhausted; raise ulimit -n")
		}
		return fmt.Errorf("cannot bind loopback (sandbox/no lo interface?): %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: net.Listen fails when the process has exhausted its file-descriptor limit (EMFILE), the loopback interface is unavailable (lo interface down, no IPv4 support in restricted containers/network namespaces), a mandatory sandbox seccomp/AppArmor policy blocks socket creation, or the system is out of memory for socket buffers.

Common situations: Running kubectx readonly mode inside a hardened container or CI sandbox with no loopback networking or low RLIMIT_NOFILE; long-running shells that leaked thousands of fds; minimal distroless images without loopback configured; corporate endpoint-protection software blocking socket creation.

Related errors


AI-assisted analysis of ahmetb/kubectx@12ad6fb22e (2026-09-02). Data as JSON: /api/errors/45013f0be19e72f6. Report an issue: GitHub.