kubernetes/kops · error
parsing kops-channels manifest: %w
Error message
parsing kops-channels manifest: %w
What it means
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.
Source
Thrown at pkg/commands/toolbox_enroll.go:1013
return nil, err
}
bootstrapData.NodeupScript = nodeupScriptBytes
bootstrapData.NodeupConfig = nodeupConfig
b.bootstrapData = bootstrapData
return bootstrapData, nil
}
// rewriteChannelsManifestForEnroll rewrites the bootstrap-channel URL in the kops-channels
// pod's container args to a file:// URL under localAddonsDir, and adds the matching hostPath
// mount so the container can read the bootstrap from the host. Custom addons pass through
// unchanged. If no arg matches the bootstrap URL we warn — the cloudup manifest shape almost
// certainly drifted and the enrolled node won't be able to reach the bootstrap channel.
func rewriteChannelsManifestForEnroll(data []byte, bootstrapChannelURL string, localAddonsDir string) ([]byte, error) {
pod := &corev1.Pod{}
if err := yaml.Unmarshal(data, pod); err != nil {
return nil, fmt.Errorf("parsing kops-channels manifest: %w", err)
}
localBootstrap := "file://" + path.Join(localAddonsDir, "bootstrap-channel.yaml")
rewroteContainer := -1
for ci := range pod.Spec.Containers {
args := pod.Spec.Containers[ci].Args
for i, arg := range args {
if arg == bootstrapChannelURL {
args[i] = localBootstrap
rewroteContainer = ci
}
}
}
if rewroteContainer < 0 {
klog.Warningf("kops-channels manifest had no arg matching the bootstrap URL %q; enrolled node will not be able to reach the bootstrap channel", bootstrapChannelURL)
return k8scodecs.ToVersionedYaml(pod)
}
kubemanifest.AddHostPathMapping(pod, &pod.Spec.Containers[rewroteContainer], "channels-enroll", localAddonsDir,
kubemanifest.WithType(corev1.HostPathDirectory))View on GitHub (pinned to 4c8573c808)
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
Example fix
// before
pod := &corev1.Pod{}
if err := yaml.Unmarshal(data, pod); err != nil {
return nil, fmt.Errorf("parsing kops-channels manifest: %w", err)
}
// after
var raw map[string]interface{}
if err := yaml.Unmarshal(data, &raw); err != nil {
return nil, fmt.Errorf("parsing kops-channels manifest: not valid YAML: %w", err)
}
if k, _ := raw["kind"].(string); k != "Pod" {
return nil, fmt.Errorf("parsing kops-channels manifest: got kind %q, want Pod", k)
}
pod := &corev1.Pod{}
if err := yaml.Unmarshal(data, pod); err != nil {
return nil, fmt.Errorf("parsing kops-channels manifest: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
func isValidPodManifest(data []byte) bool {
pod := &corev1.Pod{}
return yaml.Unmarshal(data, pod) == nil && pod.Kind == "Pod"
}
// call before: if !isValidPodManifest(data) { return nil, fmt.Errorf("invalid kops-channels manifest") } Try / catch
pod := &corev1.Pod{}
if err := yaml.Unmarshal(data, pod); err != nil {
return nil, fmt.Errorf("parsing kops-channels manifest: %w", err) // inspect wrapped err with errors.As/%v
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- rewriting channels manifest: %w
- failed to parse objects: %w
- marshaling to yaml for %v: %w
- error encoding %T: %v
- error adding needs-update label: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/0f894676ee9dd11f.
Report an issue: GitHub.