jesseduffield/lazygit · error

new key `%s' 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.

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)

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.