kubernetes/kops · error

error encoding %T with unstructured encoder: %w

Error message

error encoding %T with unstructured encoder: %w

What it means

In ToMediaTypeWithVersion, objects of type *unstructured.Unstructured are encoded via the raw serializer's Encode method. If that fails — commonly because the unstructured object lacks apiVersion/kind, or contains data invalid for the target serializer — the error is wrapped as 'error encoding %T with unstructured encoder'.

Source

Thrown at pkg/kopscodecs/codecs.go:63

// ToVersionedYaml encodes the object to YAML
func ToVersionedYaml(obj runtime.Object) ([]byte, error) {
	return ToVersionedYamlWithVersion(obj, v1alpha2.SchemeGroupVersion)
}

// ToMediaTypeWithVersion encodes the object to the specified mediaType, in a specified API version
func ToMediaTypeWithVersion(obj runtime.Object, mediaType string, gv runtime.GroupVersioner) ([]byte, error) {
	e, ok := runtime.SerializerInfoForMediaType(Codecs.SupportedMediaTypes(), mediaType)
	if !ok {
		return nil, fmt.Errorf("no serializer for %q", mediaType)
	}

	_, isUnstructured := obj.(*unstructured.Unstructured)
	var w bytes.Buffer
	if isUnstructured {
		err := e.Serializer.Encode(obj, &w)
		if err != nil {
			return nil, fmt.Errorf("error encoding %T with unstructured encoder: %w", obj, err)
		}
	} else {
		encoder := Codecs.EncoderForVersion(e.Serializer, gv)
		if err := encoder.Encode(obj, &w); err != nil {
			return nil, fmt.Errorf("error encoding %T with structured encoder: %w", obj, err)
		}
	}
	return w.Bytes(), nil
}

// ToVersionedYamlWithVersion encodes the object to YAML, in a specified API version
func ToVersionedYamlWithVersion(obj runtime.Object, version runtime.GroupVersioner) ([]byte, error) {
	return ToMediaTypeWithVersion(obj, "application/yaml", version)
}

// ToVersionedJSON encodes the object to JSON
func ToVersionedJSON(obj runtime.Object) ([]byte, error) {
	return ToVersionedJSONWithVersion(obj, v1alpha2.SchemeGroupVersion)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Set obj.Object["apiVersion"] and obj.Object["kind"] (e.g. "kops.k8s.io/v1", "Cluster") before encoding.
  2. Validate the unstructured object with unstructured helper checks before encoding.
  3. If the object is actually structured, pass the typed runtime.Object so the structured encoder path is used.

Example fix

// before
u := &unstructured.Unstructured{Object: map[string]any{"spec": spec}}
b, err := kopscodecs.ToMediaTypeWithVersion(u, "application/yaml", gv) // no GVK
// after
u := &unstructured.Unstructured{Object: map[string]any{
	"apiVersion": "kops.k8s.io/v1",
	"kind":       "Cluster",
	"spec":       spec,
}}
b, err := kopscodecs.ToMediaTypeWithVersion(u, "application/yaml", gv)
Defensive patterns

Strategy: validation

Validate before calling

func hasGVK(u *unstructured.Unstructured) bool {
	return u != nil &&
		u.GetAPIVersion() != "" &&
		u.GetKind() != ""
}
// call before encoding: if !hasGVK(u) { set apiVersion/kind first }

Try / catch

if err != nil {
	return fmt.Errorf("unstructured encode of %s/%s failed: %w", u.GetKind(), u.GetName(), err)
}

Prevention

When it happens

Trigger: Calling ToMediaTypeWithVersion (or ToVersionedYamlWithVersion / ToVersionedJSONWithVersion) with an *unstructured.Unstructured whose Object['apiVersion'] or Object['kind'] is empty, or whose content cannot be serialized (e.g. unmarshalable nested values).

Common situations: Building unstructured objects programmatically and forgetting GVK; round-tripping manifests where the kind was stripped; feeding partially-parsed YAML into an unstructured object before encoding.

Related errors


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