AlexxIT/go2rtc · error

yaml: can't patch

Error message

yaml: can't patch

What it means

pkg/yaml patch updates a value at a path inside a parsed YAML node tree. After confirming the document has exactly one root content node, it requires that node to be a mapping (dict); if the root is a scalar or sequence, a path-based patch cannot be applied and the function returns this error instead of corrupting the document. It is called by the exported Patch.

Solutions

  1. Ensure the target YAML document's root is a mapping (key: value pairs at top level)
  2. If the document is empty, write an initial mapping structure before patching
  3. Check you are patching the intended file — the error implies a scalar/sequence root

Example fix

// before (target doc: just '- item1\n- item2')
yaml.Patch(doc, []string{"key"}, "value") // error
// after (target doc root mapping)
// key: old
yaml.Patch(doc, []string{"key"}, "value") // ok
Defensive patterns

Strategy: type-guard

Validate before calling

root, err := yaml.Parse(docBytes)
if err != nil || root == nil || len(root.Content) != 1 || root.Content[0].Kind != yaml.MappingNode {
    // initialize document as a mapping before patching
}

Type guard

func isMappingRoot(root *yaml.Node) bool {
    return root != nil && len(root.Content) == 1 && root.Content[0].Kind == yaml.MappingNode
}

Try / catch

if _, err := yaml.Patch(doc, path, value); err != nil {
    if strings.Contains(err.Error(), "can't patch") {
        // rebuild the document as a mapping and re-apply
    }
    return err
}

Prevention

When it happens

Trigger: Calling yaml Patch with a path on a YAML document whose root is a plain scalar (e.g. the file contains just '42' or 'some string') or a top-level list rather than a mapping.

Common situations: Pointing the patcher at a config file that unexpectedly contains an empty document or a top-level array; a templating step flattening the YAML to a single scalar; wrong file selected for patching.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.


AI-assisted analysis of AlexxIT/go2rtc@c245815e75 (2026-09-07). Data as JSON: /api/errors/225ccc82c0f8069f. Report an issue: GitHub.

Appendix: source

Thrown at pkg/yaml/yaml.go:54

	return out, nil
}

func patch(in []byte, path []string, value any) ([]byte, error) {
	var root yaml.Node
	if err := yaml.Unmarshal(in, &root); err != nil {
		// invalid yaml
		return nil, err
	}

	// empty in
	if len(root.Content) != 1 {
		return addToEnd(in, path, value)
	}

	// yaml is not dict
	if root.Content[0].Kind != yaml.MappingNode {
		return nil, errors.New("yaml: can't patch")
	}

	// dict items list
	nodes := root.Content[0].Content

	n := len(path) - 1

	// parent node key/value
	pKey, pVal := findNode(nodes, path[:n])
	if pKey == nil {
		// no parent node
		return addToEnd(in, path, value)
	}

	var paste []byte

	if value != nil {
		// nil value means delete key

View on GitHub (pinned to c245815e75)