{"record":{"id":"e94cb968341e9bc5","repo":"kubernetes/kops","slug":"error-parsing-version-spec-q","errorCode":null,"errorMessage":"error parsing version spec %q","messagePattern":"error parsing version spec %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"channels/pkg/channels/channel_version.go","lineNumber":82,"sourceCode":"}\n\nfunc (c *ChannelVersion) String() string {\n\ts := \"Channel=\" + stringValue(c.Channel)\n\tif c.Id != \"\" {\n\t\ts += \" Id=\" + c.Id\n\t}\n\tif c.ManifestHash != \"\" {\n\t\ts += \" ManifestHash=\" + c.ManifestHash\n\t}\n\ts += \" SystemGeneration=\" + strconv.Itoa(c.SystemGeneration)\n\treturn s\n}\n\nfunc ParseChannelVersion(s string) (*ChannelVersion, error) {\n\tv := &ChannelVersion{}\n\terr := json.Unmarshal([]byte(s), v)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"error parsing version spec %q\", s)\n\t}\n\treturn v, nil\n}\n\nfunc FindChannelVersions(ns *v1.Namespace) map[string]*ChannelVersion {\n\taddons := make(map[string]*ChannelVersion)\n\tfor k, v := range ns.Annotations {\n\t\tif !strings.HasPrefix(k, AnnotationPrefix) {\n\t\t\tcontinue\n\t\t}\n\n\t\tchannelVersion, err := ParseChannelVersion(v)\n\t\tif err != nil {\n\t\t\tklog.Warningf(\"failed to parse annotation %q=%q\", k, v)\n\t\t\tcontinue\n\t\t}\n\n\t\tname := strings.TrimPrefix(k, AnnotationPrefix)","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/channels/pkg/channels/channel_version.go#L64-L100","documentation":"ParseChannelVersion unmarshals the value of an addons.k8s.io/<name> namespace annotation into a ChannelVersion struct and wraps JSON failures. It means the annotation recording installed addon state is not the expected JSON ({channel, id, manifestHash, systemGeneration}) — the state is corrupt or was written by an incompatible tool. Note FindChannelVersions only logs a warning for the same condition, while GetInstalledVersion propagates the error.","triggerScenarios":"GetInstalledVersion reads namespace annotation addons.k8s.io/<name> -> ParseChannelVersion fails when the value is not valid JSON or does not match the struct: a plain version string like '1.2.3', a truncated value, a hand-edited annotation, or a value written by an older incompatible kops format.","commonSituations":"Manual edits to namespace annotations; migration from very old kops versions that stored plain version strings; annotation truncated by a tool with size limits; copy/paste of values between addons.","solutions":["Inspect the annotation: kubectl get namespace <ns> -o jsonpath='{.metadata.annotations.addons\\.k8s\\.io/<name>}' and confirm it is valid JSON like {\"id\":\"...\",\"manifestHash\":\"...\"}.","Delete the stale annotation so the next apply re-installs and rewrites it: kubectl annotate namespace <ns> addons.k8s.io/<name>-.","Re-run 'kops update cluster --yes' to re-apply the addon and re-record the version.","Confirm the kops version matches the one that created the cluster."],"exampleFix":"# corrupt annotation: remove it so kops re-records a valid JSON value\nkubectl annotate namespace kube-system addons.k8s.io/networking.k8s.io-\n# then re-apply\nkops update cluster --yes","handlingStrategy":"validation","validationCode":"// validate annotation value before ParseChannelVersion\nfunc validChannelVersion(s string) bool {\n\tvar cv struct {\n\t\tID           string `json:\"id\"`\n\t\tManifestHash string `json:\"manifestHash\"`\n\t}\n\treturn json.Unmarshal([]byte(s), &cv) == nil && (cv.ID != \"\" || cv.ManifestHash != \"\")\n}","typeGuard":"func isChannelVersionJSON(s string) bool {\n\tvar v channels.ChannelVersion\n\treturn json.Unmarshal([]byte(s), &v) == nil\n}","tryCatchPattern":"cv, err := channels.ParseChannelVersion(raw)\nif err != nil {\n\tklog.Warningf(\"corrupt addons annotation %q, removing so it is re-applied: %v\", raw, err)\n\t// delete annotation and let the next apply rewrite it\n\tk8sClient.CoreV1().Namespaces().Patch(ctx, ns, types.StrategicMergePatchType,\n\t\t[]byte(fmt.Sprintf(`{\"metadata\":{\"annotations\":{%q:null}}}`, annotationName)), metav1.PatchOptions{})\n}","preventionTips":["Never hand-edit addons.k8s.io namespace annotations.","After kops major upgrades, re-run 'kops update cluster' to rewrite annotations.","Validate annotation JSON before any manual tweak.","Prefer tolerant scanning (FindChannelVersions warns) over GetInstalledVersion when auditing."],"tags":["json","annotations","corrupt-state","kubernetes"],"backgroundTag":"corrupt-annotation-json","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"}