{"record":{"id":"318fd17902d5317c","repo":"kubernetes/kops","slug":"evictionsoft-w","errorCode":null,"errorMessage":"evictionSoft: %w","messagePattern":"evictionSoft: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodeup/pkg/model/kubelet.go","lineNumber":394,"sourceCode":"\t\tcc.EventRecordQPS = kubeletConfig.EventQPS\n\t}\n\n\tif b.NodeupConfig.ContainerdConfig.Address == nil {\n\t\tcc.ContainerRuntimeEndpoint = \"unix:///run/containerd/containerd.sock\"\n\t} else {\n\t\tcc.ContainerRuntimeEndpoint = \"unix://\" + fi.ValueOf(b.NodeupConfig.ContainerdConfig.Address)\n\t}\n\n\tif kubeletConfig.EvictionHard != nil {\n\t\tevictionHard, err := parseKeyValueList(*kubeletConfig.EvictionHard, \"<\")\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"evictionHard: %w\", err)\n\t\t}\n\t\tcc.EvictionHard = evictionHard\n\t}\n\tevictionSoft, err := parseKeyValueList(kubeletConfig.EvictionSoft, \"<\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"evictionSoft: %w\", err)\n\t}\n\tcc.EvictionSoft = evictionSoft\n\tevictionSoftGracePeriod, err := parseKeyValueList(kubeletConfig.EvictionSoftGracePeriod, \"=\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"evictionSoftGracePeriod: %w\", err)\n\t}\n\tcc.EvictionSoftGracePeriod = evictionSoftGracePeriod\n\tevictionMinimumReclaim, err := parseKeyValueList(kubeletConfig.EvictionMinimumReclaim, \"=\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"evictionMinimumReclaim: %w\", err)\n\t}\n\tcc.EvictionMinimumReclaim = evictionMinimumReclaim\n\n\tfeatureGates, err := parseFeatureGates(kubeletConfig.FeatureGates)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"featureGates: %w\", err)\n\t}\n\tcc.FeatureGates = featureGates","sourceCodeStart":376,"sourceCodeEnd":412,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/nodeup/pkg/model/kubelet.go#L376-L412","documentation":"Same parseKeyValueList mechanism as evictionHard but applied to EvictionSoft: entries must be key<value pairs split on '<'. A comma-separated entry missing '<' aborts kubelet configuration assembly with this wrapped error.","triggerScenarios":"kubeletConfiguration -> parseKeyValueList(kubeletConfig.EvictionSoft, \"<\") fails because an entry in spec.kubelet.evictionSoft lacks the '<' separator.","commonSituations":"Mixing up separators: grace periods use '=' but evictionSoft thresholds use '<'; users copy grace-period syntax into evictionSoft; typos like \"memory.available 100Mi\" (missing separator entirely).","solutions":["Fix the offending entry to use '<' between key and value (message quotes the bad pair)","Distinguish fields: evictionSoft uses '<', evictionSoftGracePeriod and evictionMinimumReclaim use '='","Validate the CSV string locally with a quick split-and-check before applying","kops update cluster after correcting the spec"],"exampleFix":"// before\nkubelet:\n  evictionSoft: \"memory.available=100Mi\"\n// after\nkubelet:\n  evictionSoft: \"memory.available<100Mi\"","handlingStrategy":"validation","validationCode":"func validEvictionSoft(s string) bool {\n    if s == \"\" { return true }\n    for _, kv := range strings.Split(s, \",\") {\n        if !strings.Contains(kv, \"<\") { return false }\n    }\n    return true\n}","typeGuard":null,"tryCatchPattern":"if _, err := parseKeyValueList(cfg.EvictionSoft, \"<\"); err != nil {\n    return fmt.Errorf(\"evictionSoft must be comma-separated key<value pairs: %w\", err)\n}","preventionTips":["Do not copy '=' syntax from grace-period fields into evictionSoft","Each entry must contain exactly the '<' separator","Validate specs in CI with a small parse harness"],"tags":["kubelet","eviction","config-parsing"],"backgroundTag":"kubelet-eviction-config-invalid","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}