{"record":{"id":"6d258f05b54af32d","repo":"kubernetes/kops","slug":"failed-to-serialize-kops-controller-config-v","errorCode":null,"errorMessage":"failed to serialize kops-controller config: %v","messagePattern":"failed to serialize kops-controller config: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/template_functions.go","lineNumber":938,"sourceCode":"\t\t\tconfig.Server.Provider.Linode = &linode.LinodeVerifierOptions{}\n\n\t\tcase kops.CloudProviderMetal:\n\t\t\t// Use crypto public/private keys for Metal\n\t\t\tconfig.Server.PKI = &pkibootstrap.Options{}\n\n\t\tdefault:\n\t\t\treturn \"\", fmt.Errorf(\"unsupported cloud provider %s\", cluster.GetCloudProvider())\n\t\t}\n\t}\n\n\tif cluster.Spec.IsKopsControllerIPAM() {\n\t\tconfig.EnableCloudIPAM = true\n\t}\n\n\t// To avoid indentation problems, we marshal as json.  json is a subset of yaml\n\tb, err := json.Marshal(config)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to serialize kops-controller config: %v\", err)\n\t}\n\n\treturn string(b), nil\n}\n\n// KopsControllerArgv returns the args to kops-controller\nfunc (tf *TemplateFunctions) KopsControllerArgv() ([]string, error) {\n\tvar argv []string\n\n\t// Verbose, but not excessive logging\n\targv = append(argv, \"--v=2\")\n\n\targv = append(argv, \"--conf=/etc/kubernetes/kops-controller/config/config.yaml\")\n\n\treturn argv, nil\n}\n\nfunc (tf *TemplateFunctions) ExternalDNSArgv() ([]string, error) {","sourceCodeStart":920,"sourceCodeEnd":956,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/template_functions.go#L920-L956","documentation":"After building the kops-controller config struct, KopsControllerConfig serializes it with json.Marshal (JSON is a subset of YAML). If marshaling fails, this error wraps it. In practice json.Marshal of a plain struct essentially never fails, so this indicates a marshaling edge case or corruption of the config struct (e.g. unsupported types reached via embedded options).","triggerScenarios":"json.Marshal(config) returns an error inside KopsControllerConfig — effectively only if the config struct contains a value that cannot be marshaled (unsupported type, channel, func field, or a custom MarshalJSON returning an error).","commonSituations":"Extremely rare in normal use; mostly encountered when hacking on kOps itself, adding a new field of an unmarshalable type to pkibootstrap.Options or the kops-controller config struct.","solutions":["Inspect the wrapped error to identify the unmarshalable field/type.","If you added a new field to the config struct, change its type to something JSON-marshalable (or add json:\"-\").","Report upstream if hit on an unmodified kOps build."],"exampleFix":"// before\nDebug chan struct{} `json:\"debug\"`\n// after\nDebug bool `json:\"debug\"`","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Go\nb, err := json.Marshal(config)\nif err != nil {\n    // log full config struct type to locate the offending field\n    klog.Errorf(\"kops-controller config marshal failed: %v\", err)\n    return \"\", fmt.Errorf(\"failed to serialize kops-controller config: %v\", err)\n}","preventionTips":["Keep config struct fields JSON-marshalable","Avoid channels/funcs/custom marshalers in config options structs","Run unit tests rendering configs for all supported clouds"],"tags":["json","serialization","template-function"],"backgroundTag":"json-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"}