helm/helm · error
kubernetes cluster unreachable
Error message
kubernetes cluster unreachable
What it means
Returned by Client.IsReachable (pkg/kube/client.go:258) when constructing the Kubernetes client fails with client-go's genericclioptions.ErrEmptyConfig — the kubeconfig is missing, empty, or has no usable current context. Helm deliberately replaces the cryptic ErrEmptyConfig with this friendly bare message (no wrapped detail). Other failures in IsReachable produce the wrapped variant "kubernetes cluster unreachable: <err>" from lines 261/264.
Source
Thrown at pkg/kube/client.go:258
func (c *Client) getKubeClient() (kubernetes.Interface, error) {
if c.kubeClient != nil {
return c.kubeClient, nil
}
kc, err := c.Factory.KubernetesClientSet()
if err != nil {
return nil, err
}
c.kubeClient = kc
return c.kubeClient, nil
}
// IsReachable tests connectivity to the cluster.
func (c *Client) IsReachable() error {
client, err := c.getKubeClient()
if errors.Is(err, genericclioptions.ErrEmptyConfig) {
// re-replace kubernetes ErrEmptyConfig error with a friendly error
// moar workarounds for Kubernetes API breaking.
return errors.New("kubernetes cluster unreachable")
}
if err != nil {
return fmt.Errorf("kubernetes cluster unreachable: %w", err)
}
if _, err := client.Discovery().ServerVersion(); err != nil {
return fmt.Errorf("kubernetes cluster unreachable: %w", err)
}
return nil
}
type clientCreateOptions struct {
serverSideApply bool
forceConflicts bool
dryRun bool
fieldValidationDirective FieldValidationDirective
}
type ClientCreateOption func(*clientCreateOptions) errorView on GitHub (pinned to 2a29f1770b)
Solutions
- Verify and regenerate kubeconfig: `kubectl config get-contexts` / `kubectl config use-context <name>`; check `echo $KUBECONFIG`
- Point KUBECONFIG at a valid file or create one (minikube/kind/cluster setup writes it)
- When using the SDK, pass a genericclioptions.RESTClientGetter (e.g. ConfigFlags with APIServer, BearerToken, CAFile set) instead of relying on the default config loading
Example fix
// before
c := kube.New(nil) // relies on default kubeconfig discovery
if err := c.IsReachable(); err != nil { return err }
// after — explicit config
flags := genericclioptions.NewConfigFlags(true)
flags.APIServer = ptr.To("https://127.0.0.1:6443")
flags.BearerToken = ptr.To("...")
flags.CAFile = ptr.To("/path/ca.crt")
c := kube.New(flags) Defensive patterns
Strategy: validation
Validate before calling
// Validate kubeconfig usability before touching Helm
func kubeconfigUsable() error {
if os.Getenv("KUBECONFIG") == "" {
home, _ := os.UserHomeDir()
if _, err := os.Stat(filepath.Join(home, ".kube", "config")); err != nil {
return errors.New("no kubeconfig found: set KUBECONFIG or create ~/.kube/config")
}
}
return nil
} Try / catch
if err := c.IsReachable(); err != nil {
if strings.Contains(err.Error(), "kubernetes cluster unreachable") {
return fmt.Errorf("cannot reach cluster — check KUBECONFIG/context (kubectl get nodes): %w", err)
}
return err
} Prevention
- Fail fast in CI: assert kubectl config get-contexts succeeds before running helm/SDK operations
- Pass an explicit RESTClientGetter when embedding Helm instead of relying on ambient kubeconfig discovery
- Distinguish this no-config error from network failures: the bare message means no config; the ': err' variants mean config existed but connection failed
When it happens
Trigger: kube.Client.IsReachable() with KUBECONFIG unset/pointing at a nonexistent file, an empty kubeconfig, or no current-context; this is the preflight check behind `helm install/upgrade` reporting "Kubernetes cluster unreachable: ...".
Common situations: CI containers without a kubeconfig mounted; wrong KUBECONFIG path; a fresh machine that never ran kubectl config; a kubeconfig whose current-context points at a removed cluster; SDK usage without passing a RESTClientGetter.
Related errors
- kubernetes cluster unreachable: %w
- could not get Kubernetes discovery client: %w
- unable to generate config for kubernetes client: %w
- cluster reachability check failed: %w
- no repositories found. You must add one before updating
AI-assisted analysis of helm/helm@2a29f1770b (2026-08-15).
Data as JSON: /api/errors/ab8eb57f97110c2c.
Report an issue: GitHub.