derailed/k9s · error

unable to connect to context %q

Error message

unable to connect to context %q

What it means

Returned inside K9s.ActivateContext (internal/config/k9s.go:285) on the context-switch fast path: when the context's k9s config declares a proxy and k9s already holds a live connection object, the proxy is swapped onto the existing client (avoiding a full re-dial) and CheckConnectivity() is run immediately. If that check fails, activation aborts with this error naming the context. It fires only in the proxy!=nil branch — non-proxied contexts never hit it.

Source

Thrown at internal/config/k9s.go:285

	k.setActiveConfig(cfg)

	if cfg.Context.Proxy != nil {
		k.ks.SetProxy(func(*http.Request) (*url.URL, error) {
			slog.Debug("Using proxy address", slogs.Address, cfg.Context.Proxy.Address)
			return url.Parse(cfg.Context.Proxy.Address)
		})

		if k.conn != nil && k.conn.Config() != nil {
			// We get on this branch when the user switches the context and k9s
			// already has an API connection object so we just set the proxy to
			// avoid recreation using client.InitConnection
			k.conn.Config().SetProxy(func(*http.Request) (*url.URL, error) {
				slog.Debug("Setting proxy address", slogs.Address, cfg.Context.Proxy.Address)
				return url.Parse(cfg.Context.Proxy.Address)
			})

			if !k.conn.CheckConnectivity() {
				return nil, fmt.Errorf("unable to connect to context %q", contextName)
			}
		}
	}

	k.Validate(k.conn, contextName, ct.Cluster)
	// If the context specifies a namespace, use it!
	if ns := ct.Namespace; ns != client.BlankNamespace {
		k.getActiveConfig().Context.Namespace.Active = ns
	} else if k.getActiveConfig().Context.Namespace.Active == "" {
		k.getActiveConfig().Context.Namespace.Active = client.DefaultNamespace
	}
	if k.getActiveConfig().Context == nil {
		return nil, fmt.Errorf("context activation failed for: %s", contextName)
	}

	return k.getActiveConfig().Context, nil
}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Verify the proxy address in the context yaml (contexts/<cluster>/<ctx>.yaml, proxy.address) and test it: curl -x <address> https://<api-server>/version
  2. Fix the typo/port, or remove the proxy block entirely if the cluster is directly reachable
  3. Restart k9s after fixing — the check only runs on the reuse-connection path, and a fresh start rebuilds the connection through client.InitConnection
  4. If the proxy requires authentication, ensure the address scheme carries the credentials or use an authenticated local forwarder

Example fix

# before: contexts/prod-c/prod.yaml
context:
  proxy:
    address: http://corporate-proxy:808

# after (fix port)
context:
  proxy:
    address: http://corporate-proxy:8080

# or remove the block when direct access works
Defensive patterns

Strategy: validation

Validate before calling

// Before activating a context that declares a proxy, verify the address:
func proxyReachable(address, apiServer string) error {
	u, err := url.ParseRequestURI(address)
	if err != nil {
		return fmt.Errorf("bad proxy address %q: %w", address, err)
	}
	conn, err := net.DialTimeout("tcp", u.Host, 3*time.Second)
	if err != nil {
		return fmt.Errorf("proxy %q unreachable: %w", address, err)
	}
	conn.Close()
	return nil
}

Try / catch

if _, err := k9s.ActivateContext(name); err != nil {
	if strings.Contains(err.Error(), "unable to connect to context") {
		// proxy swapped onto existing conn failed connectivity:
		// fix/remove proxy address in the context yaml, then restart k9s
		// (a fresh process rebuilds the connection instead of reusing it)
	}
}

Prevention

When it happens

Trigger: A context config (contexts/<cluster>/<name>.yaml) with a proxy: block whose address is mistyped, unreachable, or requires auth, combined with switching to that context while k9s already has an API connection (e.g. pressing :ctx mid-session). Also when a corporate proxy goes down between sessions.

Common situations: Corporate/air-gapped environments routing cluster traffic through a proxy; proxy address changed by IT; copy-paste of proxy config between contexts with a stale port; VPN dropped so the proxy host no longer resolves.

Related errors


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