{"record":{"id":"e44d4386786ebe6b","repo":"abiosoft/colima","slug":"error-encoding-yaml-file-w","errorCode":null,"errorMessage":"error encoding yaml file: %w","messagePattern":"error encoding yaml file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/yamlutil/yaml.go","lineNumber":106,"sourceCode":"\t\t// no performance concern as only one file is being read\n\t\tb, err := yaml.Marshal(val)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unexpected error nested value encoding: %w\", err)\n\t\t}\n\t\tvar newNode yaml.Node\n\t\tif err := yaml.Unmarshal(b, &newNode); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"unexpected error during yaml node traversal: %w\", err)\n\t\t}\n\n\t\tif l := len(newNode.Content); l != 1 {\n\t\t\treturn nil, fmt.Errorf(\"unexpected error during yaml node traversal: doc has multiple children of len %d\", l)\n\t\t}\n\t\t*node = *newNode.Content[0]\n\t}\n\n\tb, err := encode(root)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error encoding yaml file: %w\", err)\n\t}\n\n\treturn b, nil\n}\n\nfunc traverseConfig(parentKey string, s any, vals map[string]any) {\n\ttyp := reflect.TypeOf(s)\n\tval := reflect.ValueOf(s)\n\n\t// everything else is a value, no nesting required\n\tif typ.Kind() != reflect.Struct {\n\t\tvals[parentKey] = val.Interface()\n\t\treturn\n\t}\n\n\t// traverse the struct fields recursively\n\tfor i := 0; i < typ.NumField(); i++ {\n\t\tfield := typ.Field(i)","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/abiosoft/colima/blob/c3a5f9184d83a197184f897a9f07eb3c01b3bc88/util/yamlutil/yaml.go#L88-L124","documentation":"encodeYAML (util/yamlutil/yaml.go:106) is the final step: it encodes the modified yaml.Node document back to bytes; this error wraps a failure of that encoder. The yaml encoder over a Node tree fails if the tree is in an invalid state (e.g. a node left without valid kind/content after value replacement) or the underlying writer errors. The earlier steps validate the tree, so this indicates the value-application step left the document malformed — a code bug in node handling rather than bad user config.","triggerScenarios":"A fork modification of the apply loop (yaml.go:74-102) that assigns a mismatched node kind (e.g. scalar replaced by an empty node) so the final encode chokes; extremely rarely, writer I/O failure on in-memory encode.","commonSituations":"Forks tampering with how values are merged into the node tree; concurrent config saves mutating the same tree (data race).","solutions":["If you maintain a fork, diff your changes in the apply loop against upstream and restore the *node = *newNode.Content[0] assignment semantics","Serialize config saves behind a mutex to rule out concurrent tree mutation","Report upstream with the config that triggered it and the wrapped cause","Reinstall the stock binary and retry with the same config"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := util.Save(cfg, file); err != nil {\n    if strings.Contains(err.Error(), \"error encoding yaml file\") {\n        // node tree left invalid — retry once with a fresh config load; if it\n        // persists, the config value types need review\n    }\n    return err\n}","preventionTips":["Don't fork the node-apply loop without round-trip tests","Guard config saves against concurrent mutation","Keep a known-good saved config backup for quick restore"],"tags":["yaml","encoding","internal","node-tree"],"backgroundTag":null,"analyzedSha":"c3a5f9184d83a197184f897a9f07eb3c01b3bc88","analyzedAt":"2026-08-15T18:58:08.334Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}