kubernetes/kops · error

failed to marshal object to JSON: %w

Error message

failed to marshal object to JSON: %w

What it means

In applyset's ApplyOnce, each expected object is marshaled to JSON to build a server-side apply patch. If json.Marshal of the unstructured object fails, the error is recorded per-object via results.applyError and the object is skipped. This is a client-fixable serialization failure, so the apply continues with the remaining objects.

Source

Thrown at pkg/applylib/applyset/applyset.go:144

		// If the object exists, we need to update any client-side-apply field-managers
		// Otherwise we often end up with old and new objects combined, which
		// is unexpected and can be invalid.
		if currentObj != nil {
			managedFields := &ManagedFieldsMigrator{
				NewManager: "kops",
				Client:     client,
			}
			if err := managedFields.Migrate(ctx, currentObj); err != nil {
				results.applyError(gvk, nn, err)
				continue
			}
		}

		j, err := json.Marshal(expectedObject)
		if err != nil {
			// TODO: Differentiate between server-fixable vs client-fixable errors?
			results.applyError(gvk, nn, fmt.Errorf("failed to marshal object to JSON: %w", err))
			continue
		}

		lastApplied, err := client.Patch(ctx, gvk, nn, types.ApplyPatchType, j, a.patchOptions)
		if err != nil {
			results.applyError(gvk, nn, fmt.Errorf("error from apply: %w", err))
			continue
		}

		tracker.lastApplied = lastApplied
		results.applySuccess(gvk, nn)
		tracker.isHealthy = isHealthy(lastApplied)
		results.reportHealth(gvk, nn, tracker.isHealthy)
	}
	return results, nil
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the object at the reported GVK/name and fix the offending field value so it is JSON-serializable.
  2. Ensure manifests are plain YAML/JSON: decode with sigs.k8s.io/yaml or unstructured decode, not generic YAML libs that keep native types.
  3. Check the applyset results (results.applyError output) for the exact json.Marshal error message to identify the bad field.

Example fix

// before
obj.Object["replicas"] = math.NaN()
// after
obj.Object["replicas"] = int64(3)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(expectedObject.Object); err != nil {
    return fmt.Errorf("object %s/%s not JSON-serializable: %w", expectedObject.GetNamespace(), expectedObject.GetName(), err)
}

Try / catch

if err := applyOnce(ctx); err != nil {
    var marshalErr *json.UnsupportedTypeError
    if errors.As(err, &marshalErr) {
        // fix offending field type in the manifest
    }
}

Prevention

When it happens

Trigger: An expectedObject whose underlying map contains values json.Marshal cannot encode — e.g. fields holding channels, funcs, NaN/Inf floats, or a map with non-string keys that cannot be converted — injected when the manifest was parsed or built programmatically.

Common situations: Building manifests programmatically and inserting runtime values (e.g. resource.Quantity as a struct with unencodable fields in unusual states, or float NaN from a templating bug); decoding YAML into unstructured with plugins that stash Go values in the map.

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


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