jesseduffield/lazygit · error

new key ` ' already exists

Error message

new key `%s' already exists

What it means

Returned by RenameKeyPaths/renameYamlKey in pkg/utils/yaml_utils when renaming a key inside a YAML document (lazygit's config migration machinery) and the target name already exists as a sibling key in the same mapping. The rename is aborted to avoid overwriting an existing key's value.

Solutions

  1. Open config.yml, find the mapping named in the error, and delete either the old key (keep your new-key value) or the new key (keep the old one so migration can complete)
  2. Re-run lazygit so the migration applies cleanly once no collision exists
  3. Prefer resolving manually over ignoring — the migration refuses to pick a winner for you

Example fix

# before (both keys present, migration fails)
gui:
  oldTimeFormat: '2006-01-02'
  timeFormat: '2006-01-02'

# after (remove legacy key)
gui:
  timeFormat: '2006-01-02'
Defensive patterns

Strategy: validation

Validate before calling

# before migrating, check the rename target doesn't already exist as a sibling
yq '.gui | to_entries | map(.key) | .[]' ~/.config/lazygit/config.yml

Try / catch

Catch the rename error, keep the value you want by editing config.yml manually, and re-run the migration; never overwrite the pre-existing key programmatically.

Prevention

When it happens

Trigger: A config migration renaming e.g. gui.<oldKey> to gui.<newKey> when config.yml already contains gui.<newKey> with its own value; LookupKey(node, newKey) finds a non-nil key node at the same level.

Common situations: A user already set the new-style key in config.yml before upgrading, then lazygit's version migration tries to rename the old key on top of it; hand-merged configs containing both old and new names; running an older lazygit binary against a config already migrated by a newer one, then upgrading again.

Related errors


AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15). Data as JSON: /api/errors/30fb82b18ea78950. Report an issue: GitHub.

Appendix: source

Thrown at pkg/utils/yaml_utils/yaml_utils.go:111

	return renameYamlKey(body, path, newKey)
}

// Recursive function to rename the YAML key.
func renameYamlKey(node *yaml.Node, path []string, newKey string) (error, bool) {
	if node.Kind != yaml.MappingNode {
		return errors.New("yaml node in path is not a dictionary"), false
	}

	keyNode, valueNode := LookupKey(node, path[0])
	if keyNode == nil {
		return nil, false
	}

	// end of path reached: rename key
	if len(path) == 1 {
		// Check that new key doesn't exist yet
		if newKeyNode, _ := LookupKey(node, newKey); newKeyNode != nil {
			return fmt.Errorf("new key `%s' already exists", newKey), false
		}

		keyNode.Value = newKey
		return nil, true
	}

	return renameYamlKey(valueNode, path[1:], newKey)
}

// Takes the root node of a yaml document, the path to an existing key, and the
// path at which it should live instead. If the key exists, it (and its value)
// is moved to the new path, creating intermediate mapping nodes as needed, and
// any mapping nodes left empty behind it are removed. Does nothing if the key
// at oldPath doesn't exist. Returns an error if a key already exists at newPath,
// or if a node along either path exists but isn't a mapping.
func MoveYamlKey(rootNode *yaml.Node, oldPath []string, newPath []string) (error, bool) {
	// Empty document: nothing to do.
	if len(rootNode.Content) == 0 {

View on GitHub (pinned to c477a2959b)