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
- Verify the input file contains real Kubernetes manifests with required fields (apiVersion, kind, metadata, spec)
- Render Helm/Kustomize sources to valid manifests first (`skaffold render` / `helm template`) before parsing
- 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
- Check files with util.IsKubernetesManifest before parsing
- Render Helm/Kustomize before parsing generated manifests
- Skip values files and non-manifest YAML in manifest globs
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
- c.Message (pod status condition message)
- unable to lookup minikube executable. Please add it to PATH
- rs.ae.Message (actionable error message from status check)
- no receiver was registered
- cannot resolve active Kubernetes context - multiple contexts
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/4e6b753ab3a04e41.
Report an issue: GitHub.