ahmetb/kubectx · error

failed to save kubeconfig file: %w

Error message

failed to save kubeconfig file: %w

What it means

After mutating the namespace in memory, switchNamespace persists the kubeconfig to disk via kc.Save(). This error wraps any failure writing the kubeconfig file — I/O errors, permission problems, or serialization failures. The in-memory change succeeded but was not committed. Thrown at cmd/kubens/switch.go:91.

Source

Thrown at cmd/kubens/switch.go:91

		}
		ns = prev
	}

	if !force {
		ok, err := namespaceExists(kc, ns)
		if err != nil {
			return "", fmt.Errorf("failed to query if namespace exists (is cluster accessible?): %w", err)
		}
		if !ok {
			return "", fmt.Errorf("no namespace exists with name \"%s\"", ns)
		}
	}

	if err := kc.SetNamespace(ctx, ns); err != nil {
		return "", fmt.Errorf("failed to change to namespace \"%s\": %w", ns, err)
	}
	if err := kc.Save(); err != nil {
		return "", fmt.Errorf("failed to save kubeconfig file: %w", err)
	}
	if curNS != ns {
		if err := f.Save(curNS); err != nil {
			return "", fmt.Errorf("failed to save the previous namespace to file: %w", err)
		}
	}
	return ns, nil
}

func namespaceExists(kc *kubeconfig.Kubeconfig, ns string) (bool, error) {
	// for tests
	if os.Getenv("_MOCK_NAMESPACES") != "" {
		return ns == "ns1" || ns == "ns2", nil
	}

	clientset, err := newKubernetesClientSet(kc)
	if err != nil {
		return false, fmt.Errorf("failed to initialize k8s REST client: %w", err)

View on GitHub (pinned to 12ad6fb22e)

Solutions

  1. Fix ownership/permissions: sudo chown $USER ~/.kube/config && chmod 600 ~/.kube/config
  2. Check disk space and quota: df -h ~/.kube
  3. If the file is a read-only mount (secret/configmap), write to a writable copy and point KUBECONFIG at it
  4. Verify no policy blocks writes: check mount options (mount | grep kube) and SELinux denials

Example fix

// before
-rw------- 1 root root ~/.kube/config   # kubens cannot write as normal user
// after
sudo chown $USER:$USER ~/.kube/config
kubens production
Defensive patterns

Strategy: validation

Validate before calling

cfgPath := kubeconfigPath()
if fi, err := os.Stat(cfgPath); err == nil {
    if err := syscall.Access(cfgPath, os.O_RDWR); err != nil {
        return fmt.Errorf("kubeconfig %s not writable by %s: %v", cfgPath, os.Getenv("USER"), err)
    }
    _ = fi
}

Try / catch

if err := kc.Save(); err != nil {
    var perr *os.PathError
    if errors.As(err, &perr) {
        return fmt.Errorf("cannot write %s (check ownership/permissions/disk space): %w", perr.Path, err)
    }
    return err
}

Prevention

When it happens

Trigger: kc.Save() errors because the kubeconfig file or its parent directory is not writable (read-only filesystem, wrong owner), disk is full, or an immutable attribute / LSM policy blocks the write.

Common situations: ~/.kube/config owned by root after running kubectl under sudo; read-only container filesystem; disk quota/full disk; the config file mounted read-only from a Kubernetes secret or ConfigMap in a pod; EACCES from SELinux/AppArmor.

Related errors


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