{"record":{"id":"99f09c63b4da5998","repo":"kubernetes/kops","slug":"error-parsing-addons-v","errorCode":null,"errorMessage":"error parsing addons: %v","messagePattern":"error parsing addons: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"channels/pkg/channels/addons.go","lineNumber":62,"sourceCode":"\n\treturn ParseAddons(name, location, data)\n}\n\nfunc ParseAddons(name string, location *url.URL, data []byte) (*Addons, error) {\n\tconfigString := strings.TrimSpace(string(data))\n\n\tobjects, err := kubemanifest.LoadObjectsFrom([]byte(configString))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing addons or manifest: %v\", err)\n\t}\n\n\tapiObject := &api.Addons{}\n\tif len(objects) == 0 {\n\t\t// No objects (empty, whitespace, or comment-only content): nothing to apply.\n\t} else if gvk := objects[0].GroupVersionKind(); gvk.Kind == \"Addons\" && gvk.Group == \"\" && gvk.Version == \"\" {\n\t\t// Reuse the document already parsed by LoadObjectsFrom instead of parsing it again.\n\t\tif err := objects[0].Reparse(apiObject); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error parsing addons: %v\", err)\n\t\t}\n\t} else {\n\t\tmanifest := location.String()\n\t\tmanifestHash, err := utils.HashString(configString)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error hashing manifest: %v\", err)\n\t\t}\n\t\tmanifestLocationHash, err := utils.HashString(manifest)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error hashing manifest location: %v\", err)\n\t\t}\n\t\taddonName := \"manifest-\" + manifestLocationHash[:12]\n\t\taddonSpec := &api.AddonSpec{\n\t\t\tName:         &addonName,\n\t\t\tManifest:     &manifest,\n\t\t\tManifestHash: manifestHash,\n\t\t}\n","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/addons.go#L44-L80","documentation":"ParseAddons, when the first document is a native Addons kind, re-parses it strictly into api.Addons via objects[0].Reparse and wraps failure. The YAML parsed as generic objects but does not conform to the Addons schema (missing/invalid fields, wrong types, rejected unknown fields).","triggerScenarios":"LoadAddons -> ParseAddons where objects[0] has GVK kind Addons (group/version empty) and Reparse into api.Addons fails: addon entries missing required name/manifest fields, type mismatches (e.g. unquoted numeric version), unknown fields.","commonSituations":"Custom addons channel with schema typos ('spe:' instead of 'spec:', addon items missing 'manifest'); channel written for an older kops version using removed fields; unquoted version numbers.","solutions":["Compare the addons file against the upstream kops addons channel schema and fix field names/types.","Quote version strings (version: \"1.0\") so they parse as strings.","Validate with a Go test calling ParseAddons on the file (TestParseAddons-style fixture).","Regenerate the channel from a known-good upstream template."],"exampleFix":"# before\nspec:\n  addons:\n  - name: networking\n    manifest: s3://bucket/a.yaml\n    version: 1.2   # number\n# after\nspec:\n  addons:\n  - name: networking\n    manifest: s3://bucket/a.yaml\n    version: \"1.2\"","handlingStrategy":"validation","validationCode":"// check first doc is a well-formed Addons object before Reparse\nvar probe struct {\n\tKind string                 `yaml:\"kind\"`\n\tSpec map[string]interface{} `yaml:\"spec\"`\n}\nif err := yaml.Unmarshal(data, &probe); err != nil {\n\treturn err\n}\nif probe.Kind == \"Addons\" && probe.Spec == nil {\n\treturn errors.New(\"Addons document missing spec\")\n}","typeGuard":null,"tryCatchPattern":"addons, err := channels.ParseAddons(name, location, data)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error parsing addons\") {\n\t\treturn fmt.Errorf(\"addons channel schema invalid at %s: %w\", location, err)\n\t}\n\treturn err\n}","preventionTips":["Model custom channels on the upstream kops addons file.","Quote all version fields as strings.","Validate the channel against api.Addons with a Go unit test.","Diff hand-edited channels against upstream on kops upgrades."],"tags":["yaml","schema","parsing","addons"],"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-12T07:17:12.445Z"}