{"record":{"id":"65be52d97b836bea","repo":"kubernetes/kops","slug":"failed-to-parse-objects-w-65be52","errorCode":null,"errorMessage":"failed to parse objects: %w","messagePattern":"failed to parse objects: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/pkg/channels/prune.go","lineNumber":48,"sourceCode":"\t\"k8s.io/kops/pkg/kubemanifest\"\n)\n\ntype Pruner struct {\n\tClient     dynamic.Interface\n\tRESTMapper *restmapper.DeferredDiscoveryRESTMapper\n}\n\n// Prune prunes objects not in the manifest, according to PruneSpec.\nfunc (p *Pruner) Prune(ctx context.Context, manifest []byte, spec *api.PruneSpec) error {\n\tklog.Infof(\"Prune spec: %v\", spec)\n\n\tif spec == nil {\n\t\treturn nil\n\t}\n\n\tobjects, err := kubemanifest.LoadObjectsFrom(manifest)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"failed to parse objects: %w\", err)\n\t}\n\n\tobjectsByKind := make(map[schema.GroupKind][]*kubemanifest.Object)\n\tfor _, object := range objects {\n\t\tgv, err := schema.ParseGroupVersion(object.APIVersion())\n\t\tif err != nil || gv.Version == \"\" {\n\t\t\treturn fmt.Errorf(\"failed to parse apiVersion %q\", object.APIVersion())\n\t\t}\n\t\tkind := object.Kind()\n\t\tif kind == \"\" {\n\t\t\treturn fmt.Errorf(\"failed to find kind in object\")\n\t\t}\n\n\t\tgvk := gv.WithKind(kind)\n\t\tgk := gvk.GroupKind()\n\t\tobjectsByKind[gk] = append(objectsByKind[gk], object)\n\t}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/prune.go#L30-L66","documentation":"Pruner.Prune parses the addon manifest with kubemanifest.LoadObjectsFrom to know which objects must be kept. If the manifest is not valid YAML/JSON or does not decode into Kubernetes objects, the parse error is wrapped as `failed to parse objects`. Pruning aborts before any cluster mutation.","triggerScenarios":"Prune is called (via updateAddon) with a manifest []byte that is malformed YAML, empty/garbage content, or contains documents that cannot be loaded as unstructured objects.","commonSituations":"Broken addon manifest in the channel (bad indentation, tabs, truncated download from S3); a multi-doc file with a stray non-YAML document; templating left unrendered placeholders ({{ }}) in the manifest.","solutions":["Inspect the wrapped parse error to find the offending document/line","Validate the manifest locally: `kubectl apply --dry-run=client -f manifest.yaml` or a YAML linter","Fix or re-download the addon manifest from the channel source","If the manifest is templated, ensure the template was fully rendered before Prune"],"exampleFix":"// before\nkind:  Deployment\nmetadata: [broken yaml\n// after\napiVersion: apps/v1\nkind: Deployment\nmetadata:\n  name: my-deployment","handlingStrategy":"validation","validationCode":"func validateManifest(manifest []byte) error {\n    objs, err := kubemanifest.LoadObjectsFrom(manifest)\n    if err != nil {\n        return fmt.Errorf(\"manifest not parseable: %w\", err)\n    }\n    if len(objs) == 0 {\n        return fmt.Errorf(\"manifest contains no objects\")\n    }\n    return nil\n}\n// call validateManifest(data) before Prune","typeGuard":null,"tryCatchPattern":"if err := pruner.Prune(ctx, manifest, spec); err != nil {\n    if strings.Contains(err.Error(), \"failed to parse objects\") {\n        return fmt.Errorf(\"addon manifest corrupt, skip prune: %w\", err)\n    }\n    return err\n}","preventionTips":["Lint addon manifests (yamllint / kubeconform) before publishing to the channel","Render templates fully before storing manifests; never store raw {{ }} placeholders","Verify S3/http manifest integrity after upload (checksum)"],"tags":["yaml","manifest","parsing","kubernetes"],"backgroundTag":"manifest-parse-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}