derailed/k9s · error

context with name %s already exists

Error message

context with name %s already exists

What it means

Returned by Config.RenameContext (internal/client/config.go:242) when the destination name newCtx already exists in the kubeconfig contexts map. Rename is implemented as copy-then-delete and refuses to overwrite, so an existing target aborts the operation before any mutation. The check happens after RawConfig, so kubeconfig readability is implied.

Source

Thrown at internal/client/config.go:242

	delete(cfg.Contexts, n)

	acc, err := c.ConfigAccess()
	if err != nil {
		return err
	}

	return clientcmd.ModifyConfig(acc, cfg, true)
}

// RenameContext renames a context.
func (c *Config) RenameContext(oldCtx, newCtx string) error {
	cfg, err := c.RawConfig()
	if err != nil {
		return err
	}

	if _, ok := cfg.Contexts[newCtx]; ok {
		return fmt.Errorf("context with name %s already exists", newCtx)
	}
	cfg.Contexts[newCtx] = cfg.Contexts[oldCtx]
	delete(cfg.Contexts, oldCtx)
	acc, err := c.ConfigAccess()
	if err != nil {
		return err
	}
	if e := clientcmd.ModifyConfig(acc, cfg, true); e != nil {
		return e
	}
	current, err := c.CurrentContextName()
	if err != nil {
		return err
	}
	if current == oldCtx {
		return c.SwitchContext(newCtx)
	}

View on GitHub (pinned to 2d3ccc6ba2)

Solutions

  1. Choose a different, unused target name (verify with kubectl config get-contexts)
  2. If the existing target is disposable, delete it first: kubectl config delete-context <newCtx>, then rename
  3. If both must survive, merge their settings manually instead of renaming over

Example fix

# before
cfg.RenameContext("old-cluster", "dev")  # 'dev' exists -> error

# after
kubectl config delete-context dev
cfg.RenameContext("old-cluster", "dev")
Defensive patterns

Strategy: validation

Validate before calling

func renameSafe(cfg *client.Config, oldName, newName string) error {
	ctxs, err := cfg.Contexts()
	if err != nil {
		return err
	}
	if _, exists := ctxs[newName]; exists {
		return fmt.Errorf("target name %q taken; pick another or delete it first", newName)
	}
	if _, ok := ctxs[oldName]; !ok {
		return fmt.Errorf("source context %q not found", oldName)
	}
	return cfg.RenameContext(oldName, newName)
}

Prevention

When it happens

Trigger: Calling RenameContext("old", "dev") when a context literally named 'dev' already exists; case-variant names on case-insensitive lookups; re-running a rename script that failed halfway on the second attempt.

Common situations: kubectx-style rename flows; consolidating duplicate contexts and picking a colliding name; scripted kubeconfig hygiene where the target was pre-created by another team member.

Related errors


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