kubernetes/kops · error
building json: %w
Error message
building json: %w
What it means
During generation of the containerd CNI config template for Kubenet networking (nodeup/pkg/model/containerd.go:460), the builder marshals a small slice of CNI Route structs to JSON to substitute into the {{Routes}} placeholder. This error wraps json.Marshal failure. In practice this is nearly impossible: the only data is two hardcoded string routes (0.0.0.0/0 and optionally ::/0 for IPv6-only clusters), and neither the Route struct nor its values can fail marshaling.
Source
Thrown at nodeup/pkg/model/containerd.go:460
}
]
}
`
// We will gradually build up the schema here, as needed
type Route struct {
Dest string `json:"dst"`
}
routes := []Route{
{Dest: "0.0.0.0/0"},
}
if b.IsIPv6Only() {
routes = append(routes, Route{Dest: "::/0"})
}
routesJSON, err := json.Marshal(routes)
if err != nil {
return fmt.Errorf("building json: %w", err)
}
contents = strings.ReplaceAll(contents, "{{Routes}}", string(routesJSON))
klog.V(8).Infof("Built containerd CNI config template\n%s", contents)
c.AddTask(&nodetasks.File{
Path: "/etc/containerd/config-cni.template",
Contents: fi.NewStringResource(contents),
Type: nodetasks.FileType_File,
})
return nil
}
// buildContainerdConfig builds the containerd config used for containerd >= 2.0.
// containerd 2.0 split io.containerd.grpc.v1.cri into io.containerd.cri.v1.runtime and io.containerd.cri.v1.images.
// See https://github.com/containerd/containerd/blob/main/docs/cri/config.md
// Apart from ConfigAdditions, the emitted fields load identically under config versions 3
// and 4; see containerdConfigVersion.View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the wrapped error (%w) in the message to identify which value failed to marshal
- Check recent changes to the Route struct or routes slice in buildCNIConfigTemplateFile for non-JSON-serializable field types
- Rebuild nodeup from an unmodified upstream version to confirm the failure is not from local patches
- As a workaround, verify cluster networking config (UsesKubenet, IPv6-only setting) is correct, since this code path only runs for Kubenet
Example fix
// before (hypothetical breaking change)
type Route struct {
Dest string `json:"dst"`
Hook func() // not JSON-marshalable
}
// after
type Route struct {
Dest string `json:"dst"`
} Defensive patterns
Strategy: validation
Validate before calling
// Marshal is deterministic for the fixed []Route input; guard struct changes in CI:
routes := []struct{ Dest string `json:"dst"` }{{Dest: "0.0.0.0/0"}}
if _, err := json.Marshal(routes); err != nil {
return fmt.Errorf("building json: %w", err)
} Try / catch
if _, err := json.Marshal(routes); err != nil {
return fmt.Errorf("building json: %w", err) // inspect %w for the failing value
} Prevention
- Keep the Route struct limited to JSON-serializable primitive fields
- Add a unit test that marshals the routes for both IPv4 and IPv6-only clusters
- Run go vet / lint on changes to nodeup/pkg/model/containerd.go
When it happens
Trigger: buildCNIConfigTemplateFile is invoked (cluster uses Kubenet, NodeupConfig.UsesKubenet) and json.Marshal(routes) returns an error. With the current fixed []Route{Dest string} input this cannot realistically occur; only a change to the struct (e.g. an unsupported field type like chan or func) would trigger it.
Common situations: A developer modifies the Route struct or routes slice in containerd.go to include a non-marshalable type (chan, func, complex, circular reference), then builds a Kubenet cluster; the nodeup build task fails at config template generation.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- marshalling nodeupConfig: %w
- unable to find any containerd binaries in assets
- error finding contained version
- error parsing container runtime version %q: %w
- error building containerd flags: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/f3312450be388d5e.
Report an issue: GitHub.