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
- 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)
- Re-run lazygit so the migration applies cleanly once no collision exists
- 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
- Don't pre-add new-style config keys before the version that introduces them
- Keep a backup of config.yml across upgrades so collisions are diffable
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
- Custom command prompt cannot have both a preset and a comman
- You should have an allBranchesLogCmds defined as a sequence!
- gui.sidePanels: a side panel must have at least one tab.
- gui.sidePanels must not be empty.
- gui.spinner.frames must not be empty.
AI-assisted analysis of jesseduffield/lazygit@c477a2959b (2026-08-15).
Data as JSON: /api/errors/30fb82b18ea78950.
Report an issue: GitHub.