ahmetb/kubectx · warning

failed to save the previous namespace to file: %w

Error message

failed to save the previous namespace to file: %w

What it means

If the namespace actually changed (curNS != ns), switchNamespace records the old namespace in the per-context history file via f.Save(curNS) so `kubens -` can swap back. This error wraps a failure writing that history file — a filesystem-level problem, not a cluster or kubeconfig issue. Note the kubeconfig was already saved, so the switch itself succeeded; only the back/forth bookkeeping failed. Thrown at cmd/kubens/switch.go:95.

Source

Thrown at cmd/kubens/switch.go:95

	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)
	}

	namespace, err := clientset.CoreV1().Namespaces().Get(context.Background(), ns, metav1.GetOptions{})
	if errors2.IsNotFound(err) {

View on GitHub (pinned to 12ad6fb22e)

Solutions

  1. Ensure the state directory is writable: mkdir -p ~/.kube/kubens && chmod u+w ~/.kube/kubens
  2. Check $HOME is set and writable in the environment where kubens runs
  3. Free disk space / raise quota if the filesystem is full
  4. The namespace switch already took effect; only '-' history is lost — re-save by switching namespaces once more after fixing the directory

Example fix

// before
# ~/.kube/kubens missing (cleanup job removed it)
kubens prod   # switch succeeds, history save fails
// after
mkdir -p ~/.kube/kubens
kubens default && kubens prod   # history file recreated
Defensive patterns

Strategy: fallback

Validate before calling

dir := stateDir()
if err := os.MkdirAll(dir, 0o755); err != nil {
    return fmt.Errorf("kubens state dir unwritable, '-' history disabled: %w", err)
}

Try / catch

if err := f.Save(curNS); err != nil {
    // non-fatal: namespace switch already succeeded; log and continue
    fmt.Fprintf(stderr, "warning: could not record previous namespace: %v\n", err)
}

Prevention

When it happens

Trigger: f.Save(curNS) errors because the state directory (~/.kube/kubens or XDG equivalent) does not exist and cannot be created, is read-only, has wrong permissions, or the disk is full.

Common situations: HOME unset or pointing to a read-only path in CI/cron; kubens state directory deleted by a cleanup job while the process runs; read-only root filesystem in minimal containers; disk quota exceeded.

Related errors


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