kubernetes/kops · error
applying ConfigAdditions to containerd config: %w
Error message
applying ConfigAdditions to containerd config: %w
What it means
buildContainerdConfig (nodeup/pkg/model/containerd.go:526) assembles the generated containerd config.toml (v3/v4 schema) and then applies user-supplied ConfigAdditions via applyConfigAdditions. If any ConfigAdditions entry cannot be parsed or applied, the failure is wrapped with this message. It means one of the cluster spec's spec.containerd.configAdditions entries is malformed (bad key path or unusable value), not a containerd runtime problem.
Source
Thrown at nodeup/pkg/model/containerd.go:526
config.SetPath([]string{"plugins", "io.containerd.cri.v1.runtime", "containerd", "runtimes", "runc", "runtime_type"}, "io.containerd.runc.v2")
config.SetPath([]string{"plugins", "io.containerd.cri.v1.runtime", "containerd", "runtimes", "runc", "options", "SystemdCgroup"}, true)
if b.NodeupConfig.UsesKubenet {
// Using containerd with Kubenet requires special configuration.
// This is a temporary backwards-compatible solution for kubenet users and will be deprecated when Kubenet is deprecated:
// https://github.com/containerd/containerd/blob/master/docs/cri/config.md#cni-config-template
config.SetPath([]string{"plugins", "io.containerd.cri.v1.runtime", "cni", "conf_template"}, "/etc/containerd/config-cni.template")
}
if b.InstallNvidiaRuntime() {
appendNvidiaGPURuntimeConfig(config.Table("plugins", "io.containerd.cri.v1.runtime", "containerd", "runtimes"))
}
if b.InstallGVisorRuntime() {
appendGVisorRuntimeConfig(config.Table("plugins", "io.containerd.cri.v1.runtime", "containerd", "runtimes"))
}
if err := applyConfigAdditions(config, containerd.ConfigAdditions); err != nil {
return "", fmt.Errorf("applying ConfigAdditions to containerd config: %w", err)
}
return config.String(), nil
}
// usesOSContainerd reports whether kops only configures a distro-supplied containerd,
// whose version spec.containerd.version does not identify.
func (b *ContainerdBuilder) usesOSContainerd() bool {
switch b.Distribution {
case distributions.DistributionFlatcar, distributions.DistributionContainerOS:
return true
}
return false
}
// containerdConfigVersion returns the config version to declare in the generated config.toml:
// 4 for containerd >= 2.3, otherwise 3.
// Both bounds matter: containerd 2.1 and 2.2 reject version 4, while 2.3.0-2.3.4 refuseView on GitHub (pinned to 4c8573c808)
Solutions
- Read the wrapped inner error to identify the offending key
- Fix the quoting of the offending configAdditions key in the cluster spec; plugin names with dots must be wrapped in escaped quotes, e.g. plugins."io.containerd.cri.v1.runtime".sandbox_image
- Validate the full entry parses as a CSV record with Comma='.' before deploying
- Remove the bad entry temporarily to let the node build, then re-add a corrected version
Example fix
// before (cluster spec) configAdditions: plugins."io.containerd.cri.v1.runtime.sandbox_image: registry.k8s.io/pause:3.10 // after configAdditions: plugins."io.containerd.cri.v1.runtime".sandbox_image: registry.k8s.io/pause:3.10
Defensive patterns
Strategy: validation
Validate before calling
// Validate each configAdditions key parses before applying it to the cluster:
for k := range cfg.ContainerdConfig.ConfigAdditions {
r := csv.NewReader(strings.NewReader(k))
r.Comma = '.'
if _, err := r.Read(); err != nil {
return fmt.Errorf("invalid configAdditions key %q: %w", k, err)
}
} Try / catch
if err := applyConfigAdditions(config, additions); err != nil {
return "", fmt.Errorf("applying ConfigAdditions to containerd config: %w", err)
}
// caller: errors.Unwrap(err) reveals the exact key that failed Prevention
- Quote dotted plugin names exactly as containerd docs show: plugins."io.containerd.cri.v1.runtime".field
- Validate the cluster spec with kops before rolling nodes (kops update cluster --dry-run)
- Test config changes on a single node / dev cluster first
- Match keys to the containerd config schema version (v3 vs v4) your containerd binary uses
When it happens
Trigger: Any containerd >= 2.0 node build where containerd.ConfigAdditions is non-empty and applyConfigAdditions fails — specifically when a ConfigAdditions key cannot be parsed as a dot-separated path by the CSV reader (e.g. unbalanced quotes or bare-broken CSV syntax in the key).
Common situations: Users hand-write configAdditions in the cluster spec and quote plugin names incorrectly, e.g. plugins."io.containerd...".sandbox_image with mismatched quotes, or copy keys from a v1-style config that don't fit the current schema. Build fails in nodeup before containerd ever starts.
Related errors
- error finding contained version
- parsing additional containerd config entry %q: %w
- DeviceName not set for volume
- Error too many '=' (%d) in %s
- building kubernetes client for node labeler: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/1372a3333a6915fc.
Report an issue: GitHub.