{"record":{"id":"88ae15e57386e05a","repo":"GoogleContainerTools/skaffold","slug":"marshalling-yaml-w-88ae15","errorCode":null,"errorMessage":"marshalling yaml: %w","messagePattern":"marshalling yaml: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/kubernetes/manifest/visitor.go","lineNumber":233,"sourceCode":"// Visit recursively visits all transformable object fields within the manifests and lets the visitor apply transformations/aggregations on them.\nfunc (l *ManifestList) Visit(visitor FieldVisitor, rs ResourceSelector) (ManifestList, error) {\n\tvar updated ManifestList\n\n\tfor _, manifest := range *l {\n\t\tm := make(map[string]interface{})\n\t\tif err := yaml.Unmarshal(manifest, &m); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"reading Kubernetes YAML: %w\", err)\n\t\t}\n\n\t\tif len(m) == 0 {\n\t\t\tcontinue\n\t\t}\n\n\t\ttraverseManifestFields(m, visitor, rs)\n\n\t\tupdatedManifest, err := yaml.Marshal(m)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"marshalling yaml: %w\", err)\n\t\t}\n\n\t\tupdated = append(updated, updatedManifest)\n\t}\n\n\treturn updated, nil\n}\n\n// traverseManifest traverses all transformable fields contained within the manifest.\nfunc traverseManifestFields(manifest map[string]interface{}, visitor FieldVisitor, rs ResourceSelector) {\n\tvar groupKind apimachinery.GroupKind\n\tvar apiVersion string\n\tif value, ok := manifest[\"apiVersion\"].(string); ok {\n\t\tapiVersion = value\n\t}\n\tvar kind string\n\tif value, ok := manifest[\"kind\"].(string); ok {\n\t\tkind = value","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/kubernetes/manifest/visitor.go#L215-L251","documentation":"ManifestList.Visit unmarshals each Kubernetes manifest into a generic map, applies a FieldVisitor transformation, and re-marshals the map back to YAML. This error wraps any failure from yaml.Marshal on the transformed map. Since the input came from valid YAML, this usually means a visitor injected a value that cannot be serialized back to YAML (e.g. a channel, func, or recursive structure), or a type marshalling incompatibility.","triggerScenarios":"Calling any of SetPlatformNodeAffinity, GetImagePlatforms, SetGKEARMToleration, GetImages, replaceImages, or SetLabels on a ManifestList when a FieldVisitor has mutated the manifest map with a value the YAML encoder cannot handle, or when a custom ResourceSelector injects unserializable values.","commonSituations":"Custom visitor plugins that put non-serializable values (channels, funcs, cyclic pointers) into the manifest map; YAML marshalling libraries with incompatible type registration (yaml.v2 vs yaml.v3 types like MapSlice); maps mutated concurrently during traversal.","solutions":["Inspect the wrapped error (%w cause) to identify which value failed to marshal","Fix the FieldVisitor so it only writes YAML-serializable values (string, number, bool, map, slice) into the manifest","Ensure consistent yaml library versions; convert yaml.v2-specific types (MapSlice, JSONMapSlice) to plain map[string]interface{} before mutation","If caused by a concurrency bug, ensure the manifest map is not modified from multiple goroutines while Visit runs"],"exampleFix":"// before\nobj[\"field\"] = make(chan int)\n// after\nobj[\"field\"] = \"serializable-string-value\"","handlingStrategy":"validation","validationCode":"// ensure all values in the manifest map are YAML-serializable before Visit\nfunc serializable(v interface{}) bool {\n\tswitch v.(type) {\n\tcase string, int, int64, float64, bool, nil:\n\t\treturn true\n\tcase map[string]interface{}:\n\t\tfor _, vv := range v.(map[string]interface{}) {\n\t\t\tif !serializable(vv) { return false }\n\t\t}\n\t\treturn true\n\tcase []interface{}:\n\t\tfor _, vv := range v.([]interface{}) {\n\t\t\tif !serializable(vv) { return false }\n\t\t}\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}","typeGuard":null,"tryCatchPattern":"updated, err := manifests.Visit(visitor, rs)\nif err != nil {\n\treturn fmt.Errorf(\"manifest transform failed: %w\", err) // inspect wrapped yaml cause\n}","preventionTips":["Only write plain YAML types (string, number, bool, map, slice) from FieldVisitor implementations","Avoid yaml.v2-specific types (MapSlice) when the pipeline uses yaml.v3","Test custom visitors against StatefulSet and multi-document manifests","Never mutate the manifest map from multiple goroutines"],"tags":["yaml","serialization","kubernetes"],"backgroundTag":"yaml-marshalling-failed","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}