jesseduffield/lazygit · error

yaml node in path is not a dictionary

Error message

yaml node in path is not a dictionary

What it means

renameYamlKey walks a dot-separated path in a YAML document to rename a key. If a node along the path is not a MappingNode (it is a scalar or sequence), descent cannot continue and this error is returned with 'false' meaning nothing was renamed. It means the path you asked for crosses a non-dictionary YAML value.

Source

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

}

// Takes the root node of a yaml document, a path to a key, and a new name for the key.
// Will rename the key to the new name if it exists, and do nothing otherwise.
func RenameYamlKey(rootNode *yaml.Node, path []string, newKey string) (error, bool) {
	// Empty document: nothing to do.
	if len(rootNode.Content) == 0 {
		return nil, false
	}

	body := rootNode.Content[0]

	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
	}

View on GitHub (pinned to c477a2959b)

Solutions

  1. Inspect the YAML file at the failing path; ensure every intermediate key holds a mapping (nested key: value pairs), not a scalar or list.
  2. Fix indentation — a nested block indented wrong often parses as a scalar or sequence.
  3. After correcting, retry the operation that triggered the rename.

Example fix

# before (b is a scalar; path a.b.c invalid)
a:
  b: oops
# after
a:
  b:
    c: value
Defensive patterns

Strategy: validation

Validate before calling

// Walk the path, asserting every intermediate node is a mapping before renaming:
func pathIsAllMappings(node *yaml.Node, path []string) bool {
    cur := node
    for _, key := range path[:len(path)-1] {
        if cur.Kind != yaml.MappingNode {
            return false
        }
        _, next := LookupKey(cur, key)
        if next == nil || next.Kind != yaml.MappingNode {
            return false
        }
        cur = next
    }
    return cur.Kind == yaml.MappingNode
}

Type guard

func isMappingNode(n *yaml.Node) bool {
    return n != nil && n.Kind == yaml.MappingNode
}

Prevention

When it happens

Trigger: Calling the rename helper (used e.g. by worktree/branch rename flows that rewrite config.yml or lazygit state YAML) with a path whose intermediate element resolves to a list or plain string — e.g. path 'a.b.c' where 'b:' holds '- 1' or 'b: foo'.

Common situations: A hand-edited config.yml where a mapping was accidentally replaced by a scalar or list (missing indentation, '-' bullet in the wrong place); YAML anchors collapsing structure unexpectedly.

Related errors


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