{"record":{"id":"dbe6f1da37109dac","repo":"kubernetes/kops","slug":"unable-to-find-containerd-config","errorCode":null,"errorMessage":"unable to find containerd config","messagePattern":"unable to find containerd config","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/nodemodel/wellknownassets/containerd.go","lineNumber":40,"sourceCode":"\n\t\"github.com/blang/semver/v4\"\n\n\t\"k8s.io/kops/pkg/apis/kops/model\"\n\t\"k8s.io/kops/pkg/assets\"\n\t\"k8s.io/kops/upup/pkg/fi\"\n\t\"k8s.io/kops/util/pkg/architectures\"\n\t\"k8s.io/kops/util/pkg/hashing\"\n)\n\nconst (\n\tcontainerdReleaseUrlAmd64 = \"https://github.com/containerd/containerd/releases/download/v%s/containerd-%s-linux-amd64.tar.gz\"\n\tcontainerdReleaseUrlArm64 = \"https://github.com/containerd/containerd/releases/download/v%s/containerd-%s-linux-arm64.tar.gz\"\n)\n\nfunc FindContainerdAsset(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {\n\tcontainerd := ig.RawClusterSpec().Containerd\n\tif containerd == nil {\n\t\treturn nil, fmt.Errorf(\"unable to find containerd config\")\n\t}\n\n\tcanonicalURL := \"\"\n\tknownHash := \"\"\n\n\tif containerd.Packages != nil {\n\t\tif arch == architectures.ArchitectureAmd64 && containerd.Packages.UrlAmd64 != nil && containerd.Packages.HashAmd64 != nil {\n\t\t\tcanonicalURL = fi.ValueOf(containerd.Packages.UrlAmd64)\n\t\t\tknownHash = fi.ValueOf(containerd.Packages.HashAmd64)\n\t\t}\n\t\tif arch == architectures.ArchitectureArm64 && containerd.Packages.UrlArm64 != nil && containerd.Packages.HashArm64 != nil {\n\t\t\tcanonicalURL = fi.ValueOf(containerd.Packages.UrlArm64)\n\t\t\tknownHash = fi.ValueOf(containerd.Packages.HashArm64)\n\t\t}\n\t}\n\n\tif canonicalURL == \"\" {\n\t\tversion := fi.ValueOf(containerd.Version)","sourceCodeStart":22,"sourceCodeEnd":58,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/nodemodel/wellknownassets/containerd.go#L22-L58","documentation":"FindContainerdAsset reads the containerd configuration off the instance group's cluster spec. If ig.RawClusterSpec().Containerd is nil there is no containerd config to derive a URL or version from, so the function fails fast with this sentinel error. It protects the asset pipeline from dereferencing a missing config block.","triggerScenarios":"BuildKubernetesFileAssets calls FindContainerdAsset with an instance group whose cluster spec has no containerd section set (ContainerdConfig nil) while containerd assets are requested.","commonSituations":"Older cluster manifests predating the containerd spec field; programmatically constructed InstanceGroup/test fixtures lacking the Containerd block; clusters migrated from docker runtime without adding the containerd stanza.","solutions":["Add a containerd section to the cluster spec (e.g. containerd: {version: 2.x}) and update the cluster","In code/tests, construct the InstanceGroup with a non-nil Containerd config before calling FindContainerdAsset","If containerd assets are not required, skip FindContainerdAsset for that instance group"],"exampleFix":"// before\nspec: {}\n// after\nspec:\n  containerd:\n    version: 2.1.0","handlingStrategy":"validation","validationCode":"if ig.RawClusterSpec().Containerd == nil {\n    return fmt.Errorf(\"instance group %s has no containerd config; add spec.containerd before building assets\", ig.Name)\n}","typeGuard":null,"tryCatchPattern":"asset, err := wellknownassets.FindContainerdAsset(ig, assetBuilder, arch)\nif err != nil && strings.Contains(err.Error(), \"unable to find containerd config\") {\n    return fmt.Errorf(\"cluster spec is missing the containerd block: %w\", err)\n}","preventionTips":["Always include the containerd section when templating cluster specs","Run kops cluster validation/lint before asset building","In tests, use shared fixture helpers that populate Containerd config"],"tags":["containerd","missing-config","cluster-spec"],"backgroundTag":"missing-config-block","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"}