{"record":{"id":"c66b9aee6a22a133","repo":"kubernetes/kops","slug":"invalid-addon-location-q","errorCode":null,"errorMessage":"invalid addon location: %q","messagePattern":"invalid addon location: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/clusteraddons/load.go","lineNumber":37,"sourceCode":"import (\n\t\"fmt\"\n\t\"net/url\"\n\n\t\"k8s.io/klog/v2\"\n\t\"k8s.io/kops/pkg/kubemanifest\"\n\t\"k8s.io/kops/util/pkg/vfs\"\n)\n\ntype ClusterAddon struct {\n\tRaw     string\n\tObjects kubemanifest.ObjectList\n}\n\n// LoadClusterAddon loads a set of objects from the specified VFS location\nfunc LoadClusterAddon(vfsContext *vfs.VFSContext, location string) (*ClusterAddon, error) {\n\tu, err := url.Parse(location)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"invalid addon location: %q\", location)\n\t}\n\n\t// TODO: Should we support relative paths for \"standard\" addons?  See equivalent code in LoadChannel\n\n\tresolved := u.String()\n\tklog.V(2).Infof(\"Loading addon from %q\", resolved)\n\taddonBytes, err := vfsContext.ReadFile(resolved)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error reading addon %q: %v\", resolved, err)\n\t}\n\taddon, err := ParseClusterAddon(addonBytes)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing addon %q: %v\", resolved, err)\n\t}\n\tklog.V(4).Infof(\"Addon contents: %s\", string(addonBytes))\n\n\treturn addon, nil\n}","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/clusteraddons/load.go#L19-L55","documentation":"LoadClusterAddon parses the addon location string as a URL before resolving it via VFS. If url.Parse rejects the string (control characters, invalid percent-escapes, etc.) the addon location is reported as invalid. This happens before any network/VFS access.","triggerScenarios":"Calling LoadClusterAddon with a location string that is not a parsable URL — e.g. contains spaces or raw control bytes, malformed % sequences (like %zz), or is otherwise corrupt in the channel/cluster manifest.","commonSituations":"Hand-edited cluster spec addons lists with typos; copy-pasted locations with invisible characters; addon locations with unencoded special characters.","solutions":["Correct the addon location string in the cluster/channel manifest so it is a valid URL or absolute path.","URL-encode special characters (spaces -> %20, etc.) in the location.","Remove the broken addon entry and re-add it using the canonical addon location from the kops addons repo."],"exampleFix":"// before\naddon, err := LoadClusterAddon(vfs.Context, \"https://addons.k8s.io/ networking addon\")\n// after\naddon, err := LoadClusterAddon(vfs.Context, \"https://addons.k8s.io/networking-addon.yaml\")","handlingStrategy":"validation","validationCode":"if _, err := url.Parse(location); err != nil {\n  return fmt.Errorf(\"addon location %q is not a valid URL: %v\", location, err)\n}","typeGuard":null,"tryCatchPattern":"addon, err := LoadClusterAddon(vfs.Context, loc)\nif err != nil && strings.Contains(err.Error(), \"invalid addon location\") {\n  return fmt.Errorf(\"fix addons entry in cluster spec: %w\", err)\n}","preventionTips":["Keep addon locations as clean absolute URLs without spaces or raw bytes.","URL-encode special characters in locations.","Validate cluster/channel manifests after hand edits."],"tags":["clusteraddons","url","parsing","validation"],"backgroundTag":"invalid-url-location","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"}