GoogleContainerTools/skaffold · error

no valid Kubernetes objects decoded

Error message

no valid Kubernetes objects decoded

What it means

ParseKubernetesObjects decodes YAML/JSON documents into Kubernetes objects and filters out documents lacking required k8s manifest fields. If every document was skipped (or the input was empty), it returns this error instead of an empty slice, so callers like IsKubernetesManifest and ParseImagesFromKubernetesYaml know the file is not a usable Kubernetes manifest.

Source

Thrown at pkg/skaffold/kubernetes/util.go:113

			break
		}
		if err != nil {
			return nil, fmt.Errorf("reading config file: %w", err)
		}

		obj := make(yamlObject)
		if err := yaml.Unmarshal(doc, &obj); err != nil {
			return nil, fmt.Errorf("reading Kubernetes YAML: %w", err)
		}

		if !hasRequiredK8sManifestFields(obj) {
			continue
		}

		k8sObjects = append(k8sObjects, obj)
	}
	if len(k8sObjects) == 0 {
		return nil, errors.New("no valid Kubernetes objects decoded")
	}
	return k8sObjects, nil
}

func hasRequiredK8sManifestFields(doc map[string]interface{}) bool {
	for _, field := range requiredFields {
		if _, ok := doc[field]; !ok {
			log.Entry(context.TODO()).Debugf("%s not present in yaml, continuing", field)
			return false
		}
	}
	return true
}

// adapted from pkg/skaffold/deploy/kubectl/recursiveReplaceImage()
func parseImagesFromYaml(obj interface{}) []string {
	var images []string

View on GitHub (pinned to a1189de023)

Solutions

  1. Verify the input file contains real Kubernetes manifests with required fields (apiVersion, kind, metadata, spec)
  2. Render Helm/Kustomize sources to valid manifests first (`skaffold render` / `helm template`) before parsing
  3. Check the pipeline's manifest configuration so raw templates are not passed as final manifests

Example fix

// before
objs, err := util.ParseKubernetesObjects(reader) // "no valid Kubernetes objects decoded"
// after
if util.IsKubernetesManifest(path) {
  objs, err := util.ParseKubernetesObjects(reader)
}
Defensive patterns

Strategy: validation

Validate before calling

if strings.TrimSpace(content) == "" { return errors.New("empty manifest input") }
docs := parseYAML(content)
for _, d := range docs { if d["apiVersion"] == nil || d["kind"] == nil { return fmt.Errorf("not a k8s manifest: %v", d) } }

Type guard

func looksLikeK8sManifest(doc map[string]interface{}) bool {
  _, hasAPI := doc["apiVersion"]; _, hasKind := doc["kind"]
  return hasAPI && hasKind
}

Try / catch

objs, err := util.ParseKubernetesObjects(r)
if err != nil {
  if strings.Contains(err.Error(), "no valid Kubernetes objects decoded") { return fmt.Errorf("%s is not a Kubernetes manifest: %w", path, err) }
  return err
}

Prevention

When it happens

Trigger: Calling ParseKubernetesObjects on a file/reader whose documents all fail hasRequiredK8sManifestFields (missing apiVersion/kind/etc.), or on an empty manifest list.

Common situations: Passing a values.yaml, docker-compose file, or plain config to a command expecting Kubernetes manifests; manifests wrapped in non-standard top-level keys; empty file generated by a failed template render.

Related errors


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