kubernetes/kops · error

error converting nodeup config to yaml: %w

Error message

error converting nodeup config to yaml: %w

What it means

GetBootstrapData serializes the fully remapped nodeup config (the per-instance-group NodeUpConfig) to YAML so it can be staged on the node's local filesystem. yaml.Marshal of nodeupConfig virtually never fails for well-formed structs; if it does, this wrapper reports the failure and aborts bootstrap data generation.

Source

Thrown at pkg/commands/toolbox_enroll.go:974

			)
			if err != nil {
				return nil, fmt.Errorf("rewriting channels manifest: %w", err)
			}
			bootstrapData.NodeupScriptAdditionalFiles[nodeupConfig.ChannelsManifest] = rewritten
		}

		if nodeupConfig.ConfigStore != nil {
			if err := remapTree(&nodeupConfig.ConfigStore.Keypairs, path.Join(targetDir, "pki/etcd")); err != nil {
				return nil, err
			}
			if err := remapTree(&nodeupConfig.ConfigStore.Secrets, path.Join(targetDir, "pki")); err != nil {
				return nil, err
			}
		}

		nodeupConfigBytes, err := yaml.Marshal(nodeupConfig)
		if err != nil {
			return nil, fmt.Errorf("error converting nodeup config to yaml: %w", err)
		}
		// Not much reason to hash this, since we're reading it from the local file system
		// sum256 := sha256.Sum256(nodeupConfigBytes)
		// bootConfig.NodeupConfigHash = base64.StdEncoding.EncodeToString(sum256[:])

		p := path.Join(targetDir, "igconfig", bootConfig.InstanceGroupRole.ToLowerString(), ig.Name, "nodeupconfig.yaml")
		bootstrapData.NodeupScriptAdditionalFiles[p] = nodeupConfigBytes

		// Copy any static manifests we need on the control plane
		for _, staticManifest := range assetBuilder.StaticManifests() {
			if !staticManifest.AppliesToRole(bootConfig.InstanceGroupRole) {
				continue
			}
			p := path.Join(targetDir, staticManifest.Path)
			bootstrapData.NodeupScriptAdditionalFiles[p] = staticManifest.Contents
		}
	}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped inner error from the message — it names the offending Go type or cycle; fix that field on NodeUpConfig (or your fork's added fields) to be YAML-serializable.
  2. If introduced by a dependency upgrade, pin/align k8s.io/apimachinery and sigs.k8s.io/yaml versions (go mod tidy / make gomod) and rebuild.
  3. Ensure any custom fields added to NodeUpConfig have yaml tags and supported types (string keys in maps, no funcs/channels/cycles).
  4. Retry on stock (unforked) kops at the cluster's version to confirm the failure is fork/dependency related.

Example fix

// before: unserializable custom field on NodeUpConfig
type NodeUpConfig struct {
    ExtraHooks map[net.IP]string `json:"extraHooks,omitempty"`
}
// after: use a string-keyed map
type NodeUpConfig struct {
    ExtraHooks map[string]string `json:"extraHooks,omitempty"`
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-flight: ensure the NodeUpConfig can round-trip through YAML before enroll
if _, err := yaml.Marshal(nodeupConfig); err != nil {
    return fmt.Errorf("nodeup config not serializable: %w", err)
}

Type guard

func yamSerializable(v interface{}) bool {
    _, err := yaml.Marshal(v)
    return err == nil
}

Try / catch

bootstrapData, err := GetBootstrapData(ctx, ...)
if err != nil {
    if strings.Contains(err.Error(), "converting nodeup config to yaml") {
        // log the wrapped cause naming the offending type, and stop — this is a code/dependency bug, not transient
        klog.Fatalf("non-transient serialization failure: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: GetBootstrapData (via getNodeConfig / RunToolboxEnroll / buildBootstrapData) reaching the yaml.Marshal(nodeupConfig) call with a value the yaml encoder cannot represent — e.g. an unsupported type (chan/func/cyclic reference) introduced by custom code or an incompatibility between the vendored k8s.io/apimachinery types and the sigs.k8s.io/yaml encoder after a dependency upgrade.

Common situations: Custom kops forks adding fields with non-serializable types to NodeUpConfig; dependency bumps (gopkg.in/yaml.v2/v3 vs sigs.k8s.io/yaml) changing marshal semantics; maps with non-string keys added to the config struct.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/6281464cd44e807c. Report an issue: GitHub.