{"record":{"id":"54d7c07e956c9ee8","repo":"kubernetes/kops","slug":"error-converting-boot-config-to-yaml-w","errorCode":null,"errorMessage":"error converting boot config to yaml: %w","messagePattern":"error converting boot config to yaml: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/model/resources/nodeup.go","lineNumber":353,"sourceCode":"\t\t\tif b.NodeUpAssets[architectures.ArchitectureAmd64] != nil {\n\t\t\t\treturn b.NodeUpAssets[architectures.ArchitectureAmd64].Hash.Hex()\n\t\t\t}\n\t\t\treturn \"\"\n\t\t},\n\t\t\"NodeUpSourceArm64\": func() (string, error) {\n\t\t\treturn b.nodeUpSource(architectures.ArchitectureArm64)\n\t\t},\n\t\t\"NodeUpSourceHashArm64\": func() string {\n\t\t\tif b.NodeUpAssets[architectures.ArchitectureArm64] != nil {\n\t\t\t\treturn b.NodeUpAssets[architectures.ArchitectureArm64].Hash.Hex()\n\t\t\t}\n\t\t\treturn \"\"\n\t\t},\n\n\t\t\"KubeEnv\": func() (string, error) {\n\t\t\tbootConfigData, err := utils.YamlMarshal(b.BootConfig)\n\t\t\tif err != nil {\n\t\t\t\treturn \"\", fmt.Errorf(\"error converting boot config to yaml: %w\", err)\n\t\t\t}\n\n\t\t\treturn string(bootConfigData), nil\n\t\t},\n\n\t\t\"GzipBase64\": gzipBase64,\n\n\t\t\"CompressUserData\": func() bool {\n\t\t\treturn b.CompressUserData\n\t\t},\n\n\t\t\"GetCloudProvider\": func() string {\n\t\t\treturn b.CloudProvider\n\t\t},\n\n\t\t\"SetSysctls\": func() string {\n\t\t\treturn b.SetSysctls\n\t\t},","sourceCodeStart":335,"sourceCodeEnd":371,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/model/resources/nodeup.go#L335-L371","documentation":"Inside the KubeEnv template function, the NodeUpScript's BootConfig struct is serialized to YAML with utils.YamlMarshal to be embedded in the nodeup script. This error is thrown if that marshal fails. It is rare because BootConfig is a plain struct, but a failure here means the bootstrap data cannot be produced.","triggerScenarios":"Build executing the KubeEnv template function while YamlMarshal fails on b.BootConfig — e.g. a BootConfig field holding a value the YAML encoder cannot represent (unsupported type such as a channel/func-bearing field or an invalid marshaling state introduced by upstream changes).","commonSituations":"Custom builds with modified BootConfig types, vendored forks with non-serializable fields, or corrupted/nonsensical BootConfig values injected programmatically.","solutions":["Check the wrapped marshal error for the offending field/type.","Ensure BootConfig is the standard nodeup.BootConfig struct populated through normal kops constructors.","If you modified BootConfig, make all new fields YAML-serializable (no channels, funcs, or cycles).","Upgrade/align kops versions so BootConfig matches what the template expects."],"exampleFix":"// before\ntype BootConfig struct { Callback func() `yaml:\"callback\"` } // not marshallable\n// after\ntype BootConfig struct { Config string `json:\"config\"` }","handlingStrategy":"try-catch","validationCode":"if _, err := utils.YamlMarshal(b.BootConfig); err != nil {\n    return fmt.Errorf(\"boot config not yaml-marshalable: %w\", err)\n}","typeGuard":"func marshalable(v interface{}) bool { _, err := utils.YamlMarshal(v); return err == nil }","tryCatchPattern":"data, err := utils.YamlMarshal(b.BootConfig)\nif err != nil {\n    return fmt.Errorf(\"inspect BootConfig fields for non-serializable types: %w\", err)\n}","preventionTips":["Keep BootConfig limited to YAML-serializable field types","Round-trip marshal BootConfig in unit tests after struct changes","Avoid channels, funcs, and cyclic references in bootstrap structs"],"tags":["yaml","serialization","nodeup","bootconfig"],"backgroundTag":"yaml-marshal-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}