{"record":{"id":"606cea3ad245c63f","repo":"GoogleContainerTools/skaffold","slug":"reading-kubernetes-yaml-w-606cea","errorCode":null,"errorMessage":"reading Kubernetes YAML: %w","messagePattern":"reading Kubernetes YAML: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/kubernetes/manifest/visitor.go","lineNumber":222,"sourceCode":"\t\tLabels:    []string{\".spec.template.metadata.labels\"},\n\t},\n}\n\n// FieldVisitor represents the aggregation/transformation that should be performed on each traversed field.\ntype FieldVisitor interface {\n\t// Visit is called for each transformable key contained in the object and may apply transformations/aggregations on it.\n\t// It should return true to allow recursive traversal or false when the entry was transformed.\n\tVisit(gk apimachinery.GroupKind, navpath string, object map[string]interface{}, key string, value interface{}, rs ResourceSelector) bool\n}\n\n// 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}","sourceCodeStart":204,"sourceCodeEnd":240,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/kubernetes/manifest/visitor.go#L204-L240","documentation":"ManifestList.Visit unmarshals each manifest document into map[string]interface{} with yaml.Unmarshal before applying a FieldVisitor. Malformed or non-mapping YAML (invalid syntax, tabs, documents that are lists/scalars) fails unmarshalling and is wrapped as 'reading Kubernetes YAML', aborting the whole visit.","triggerScenarios":"Calling Visit (via SetLabels, GetImages, replaceImages, SetPlatformNodeAffinity, etc.) on a ManifestList containing syntactically invalid YAML, or YAML whose root is not a map (e.g. a top-level list), including multi-doc lists where one document is broken.","commonSituations":"Helm/kustomize output containing template placeholders ({{ }}) left unrendered; YAML with tabs instead of spaces; JSON/YAML merge errors; a LIST (kind: List) or raw string fed in where an object was expected.","solutions":["Validate each manifest with a YAML parser or `kubectl apply --dry-run=client` to find the broken document","Fix the syntax error (tabs, unquoted special chars, unrendered templates) in the offending manifest","Ensure every document in the manifest list is a single YAML mapping (not a top-level array); render templates fully before passing to Skaffold"],"exampleFix":"# before (tabs / template placeholder)\nmetadata:\n\tname: {{ .Name }}\n# after\nmetadata:\n  name: my-app  # rendered value, spaces for indentation","handlingStrategy":"validation","validationCode":"doc := make(map[string]interface{})\nif err := yaml.Unmarshal(manifestBytes, &doc); err != nil {\n    return fmt.Errorf(\"invalid manifest YAML: %w\", err)\n}\nif len(doc) == 0 {\n    return nil // skip empty document before Visit\n}","typeGuard":"func isYAMLMap(b []byte) bool {\n    var m map[string]interface{}\n    return yaml.Unmarshal(b, &m) == nil && len(m) > 0\n}","tryCatchPattern":"updated, err := manifests.Visit(visitor, rs)\nif err != nil && strings.Contains(err.Error(), \"reading Kubernetes YAML\") {\n    // locate offending document, validate with yamllint, then retry\n    return err\n}","preventionTips":["Run yamllint/kubeconform on all rendered manifests before visiting","Fully render Helm/kustomize templates — no leftover {{ }} placeholders","Use spaces, never tabs, for YAML indentation","Ensure each document root is a mapping, not a list or scalar"],"tags":["yaml","kubernetes","parsing","manifests"],"backgroundTag":"yaml-unmarshal-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"}