GoogleContainerTools/skaffold · error

reading Kubernetes YAML: %w

Error message

reading Kubernetes YAML: %w

What it means

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.

Source

Thrown at pkg/skaffold/kubernetes/manifest/visitor.go:222

		Labels:    []string{".spec.template.metadata.labels"},
	},
}

// FieldVisitor represents the aggregation/transformation that should be performed on each traversed field.
type FieldVisitor interface {
	// Visit is called for each transformable key contained in the object and may apply transformations/aggregations on it.
	// It should return true to allow recursive traversal or false when the entry was transformed.
	Visit(gk apimachinery.GroupKind, navpath string, object map[string]interface{}, key string, value interface{}, rs ResourceSelector) bool
}

// Visit recursively visits all transformable object fields within the manifests and lets the visitor apply transformations/aggregations on them.
func (l *ManifestList) Visit(visitor FieldVisitor, rs ResourceSelector) (ManifestList, error) {
	var updated ManifestList

	for _, manifest := range *l {
		m := make(map[string]interface{})
		if err := yaml.Unmarshal(manifest, &m); err != nil {
			return nil, fmt.Errorf("reading Kubernetes YAML: %w", err)
		}

		if len(m) == 0 {
			continue
		}

		traverseManifestFields(m, visitor, rs)

		updatedManifest, err := yaml.Marshal(m)
		if err != nil {
			return nil, fmt.Errorf("marshalling yaml: %w", err)
		}

		updated = append(updated, updatedManifest)
	}

	return updated, nil
}

View on GitHub (pinned to a1189de023)

Solutions

  1. Validate each manifest with a YAML parser or `kubectl apply --dry-run=client` to find the broken document
  2. Fix the syntax error (tabs, unquoted special chars, unrendered templates) in the offending manifest
  3. Ensure every document in the manifest list is a single YAML mapping (not a top-level array); render templates fully before passing to Skaffold

Example fix

# before (tabs / template placeholder)
metadata:
	name: {{ .Name }}
# after
metadata:
  name: my-app  # rendered value, spaces for indentation
Defensive patterns

Strategy: validation

Validate before calling

doc := make(map[string]interface{})
if err := yaml.Unmarshal(manifestBytes, &doc); err != nil {
    return fmt.Errorf("invalid manifest YAML: %w", err)
}
if len(doc) == 0 {
    return nil // skip empty document before Visit
}

Type guard

func isYAMLMap(b []byte) bool {
    var m map[string]interface{}
    return yaml.Unmarshal(b, &m) == nil && len(m) > 0
}

Try / catch

updated, err := manifests.Visit(visitor, rs)
if err != nil && strings.Contains(err.Error(), "reading Kubernetes YAML") {
    // locate offending document, validate with yamllint, then retry
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/606cea3ad245c63f. Report an issue: GitHub.