{"record":{"id":"0f894676ee9dd11f","repo":"kubernetes/kops","slug":"parsing-kops-channels-manifest-w-0f8946","errorCode":null,"errorMessage":"parsing kops-channels manifest: %w","messagePattern":"parsing kops-channels manifest: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":1013,"sourceCode":"\t\treturn nil, err\n\t}\n\tbootstrapData.NodeupScript = nodeupScriptBytes\n\tbootstrapData.NodeupConfig = nodeupConfig\n\n\tb.bootstrapData = bootstrapData\n\n\treturn bootstrapData, nil\n}\n\n// rewriteChannelsManifestForEnroll rewrites the bootstrap-channel URL in the kops-channels\n// pod's container args to a file:// URL under localAddonsDir, and adds the matching hostPath\n// mount so the container can read the bootstrap from the host. Custom addons pass through\n// unchanged. If no arg matches the bootstrap URL we warn — the cloudup manifest shape almost\n// certainly drifted and the enrolled node won't be able to reach the bootstrap channel.\nfunc rewriteChannelsManifestForEnroll(data []byte, bootstrapChannelURL string, localAddonsDir string) ([]byte, error) {\n\tpod := &corev1.Pod{}\n\tif err := yaml.Unmarshal(data, pod); err != nil {\n\t\treturn nil, fmt.Errorf(\"parsing kops-channels manifest: %w\", err)\n\t}\n\tlocalBootstrap := \"file://\" + path.Join(localAddonsDir, \"bootstrap-channel.yaml\")\n\trewroteContainer := -1\n\tfor ci := range pod.Spec.Containers {\n\t\targs := pod.Spec.Containers[ci].Args\n\t\tfor i, arg := range args {\n\t\t\tif arg == bootstrapChannelURL {\n\t\t\t\targs[i] = localBootstrap\n\t\t\t\trewroteContainer = ci\n\t\t\t}\n\t\t}\n\t}\n\tif rewroteContainer < 0 {\n\t\tklog.Warningf(\"kops-channels manifest had no arg matching the bootstrap URL %q; enrolled node will not be able to reach the bootstrap channel\", bootstrapChannelURL)\n\t\treturn k8scodecs.ToVersionedYaml(pod)\n\t}\n\tkubemanifest.AddHostPathMapping(pod, &pod.Spec.Containers[rewroteContainer], \"channels-enroll\", localAddonsDir,\n\t\tkubemanifest.WithType(corev1.HostPathDirectory))","sourceCodeStart":995,"sourceCodeEnd":1031,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L995-L1031","documentation":"rewriteChannelsManifestForEnroll unmarshals the embedded kops-channels static pod manifest into a corev1.Pod before rewriting the bootstrap-channel URL to a local file:// path. This error wraps the YAML unmarshal failure, meaning the byte slice passed in was not parseable as a Kubernetes Pod manifest. It guards the rest of the rewrite logic (container arg rewriting and hostPath mounting) from operating on garbage data.","triggerScenarios":"Calling rewriteChannelsManifestForEnroll (via GetBootstrapData during toolbox enroll) with manifest bytes that are not valid YAML, are JSON/YAML of a non-Pod object, or contain fields incompatible with corev1.Pod after strict/lossless conversion by sigs.k8s.io/yaml.","commonSituations":"kOps cloudup changes the shape or serialization of the embedded kops-channels manifest so it no longer parses as a Pod; a user or tooling pre-modified/truncated the manifest file; bundle packaging injected placeholder text or an empty file where the Pod manifest should be.","solutions":["Inspect the wrapped inner error (%w) to find the exact YAML/decode failure line or type mismatch","Dump the input bytes and validate them with `kubectl apply --dry-run=client -f -` or sigs.k8s.io/yaml.Unmarshal into corev1.Pod yourself","Verify the manifest embedded/produced by cloudup matches the current kOps version; rebuild or re-extract the manifest if it was customized","Ensure the manifest is a full Pod object (apiVersion: v1, kind: Pod) rather than a fragment such as a bare container spec"],"exampleFix":"// before\npod := &corev1.Pod{}\nif err := yaml.Unmarshal(data, pod); err != nil {\n\treturn nil, fmt.Errorf(\"parsing kops-channels manifest: %w\", err)\n}\n// after\nvar raw map[string]interface{}\nif err := yaml.Unmarshal(data, &raw); err != nil {\n\treturn nil, fmt.Errorf(\"parsing kops-channels manifest: not valid YAML: %w\", err)\n}\nif k, _ := raw[\"kind\"].(string); k != \"Pod\" {\n\treturn nil, fmt.Errorf(\"parsing kops-channels manifest: got kind %q, want Pod\", k)\n}\npod := &corev1.Pod{}\nif err := yaml.Unmarshal(data, pod); err != nil {\n\treturn nil, fmt.Errorf(\"parsing kops-channels manifest: %w\", err)\n}","handlingStrategy":"validation","validationCode":"func isValidPodManifest(data []byte) bool {\n\tpod := &corev1.Pod{}\n\treturn yaml.Unmarshal(data, pod) == nil && pod.Kind == \"Pod\"\n}\n// call before: if !isValidPodManifest(data) { return nil, fmt.Errorf(\"invalid kops-channels manifest\") }","typeGuard":null,"tryCatchPattern":"pod := &corev1.Pod{}\nif err := yaml.Unmarshal(data, pod); err != nil {\n\treturn nil, fmt.Errorf(\"parsing kops-channels manifest: %w\", err) // inspect wrapped err with errors.As/%v\n}","preventionTips":["Always ship full Pod objects (apiVersion: v1, kind: Pod) in the embedded manifest, not fragments","Validate the manifest with kubectl --dry-run or sigs.k8s.io/yaml in CI before enrolling","Pin/verify kOps and manifest bundle versions so the embedded manifest shape matches the code expectations","Keep the wrapped %w error intact so the inner YAML line/column details are visible"],"tags":["yaml","kubernetes","manifest-parsing","enrollment"],"backgroundTag":"manifest-yaml-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"}