kubernetes/kops · error

unhandled kind %q in %s

Error message

unhandled kind %q in %s

What it means

`kops create -f` only understands Cluster, InstanceGroup, SSHCredential, and unstructured add-on objects. Any other kind decoded from the input file falls into the default branch and aborts the whole command with this error naming the GroupVersionKind and the file.

Source

Thrown at cmd/kops/create.go:210

				sshCredentialStore, err := clientset.SSHCredentialStore(cluster)
				if err != nil {
					return err
				}

				sshKeyArr := []byte(v.Spec.PublicKey)
				err = sshCredentialStore.AddSSHPublicKey(ctx, sshKeyArr)
				if err != nil {
					return err
				}
				fmt.Fprintf(&sb, "Added ssh credential\n")

			case *unstructured.Unstructured:
				addons = append(addons, kubemanifest.NewObject(v.Object))

			default:
				klog.V(2).Infof("Type of object was %T", v)
				return fmt.Errorf("unhandled kind %q in %s", gvk, f)
			}
		}
	}

	// Because not all addons support labels, we can only support one cluster here.
	// A single cluster per create is probably a good idea anyway.
	if len(addons) != 0 {
		if len(clusters) > 1 {
			return fmt.Errorf("cannot specify additional objects when multiple clusters are created")
		}
		if len(clusters) == 0 {
			return fmt.Errorf("must specify a cluster when creating additional objects")
		}
		cluster := clusters[0]

		addonsClient := clientset.AddonsFor(cluster)

		if err := addonsClient.Replace(addons); err != nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Remove unsupported kind documents from the -f file and manage them with `kops apply`/`kops replace`
  2. Fix the kind/apiVersion spelling to one of Cluster, InstanceGroup, SSHCredential
  3. Split the file so kops-specific resources go through `kops create -f` and add-ons through `kops replace -f` (unstructured)
  4. Check `kops create -f file --dry-run` output to see which section is offending

Example fix

# before
kind: Keyset
metadata:
  name: apiserver-aggregator-ca
# after (remove from create -f input; apply instead)
# kops apply -f file.yaml
Defensive patterns

Strategy: type-guard

Validate before calling

allowed := map[string]bool{"Cluster": true, "InstanceGroup": true, "SSHCredential": true}
for _, doc := range docs {
    if !allowed[doc.Kind] {
        return fmt.Errorf("kind %s not supported by kops create -f", doc.Kind)
    }
}

Type guard

func isSupportedKopsObject(o runtime.Object) bool {
    switch o.(type) {
    case *kopsapi.Cluster, *kopsapi.InstanceGroup, *kopsapi.SSHCredential, *unstructured.Unstructured:
        return true
    }
    return false
}

Prevention

When it happens

Trigger: `kops create -f file.yaml` containing e.g. kind: Keyset, kind: ClusterConfiguration, a Kubernetes core/v1 object, or a typo'd/unknown kind string that decodes to a non-supported type.

Common situations: Feeding a full cluster spec bundle (keysets, configs) to plain `kops create` instead of `kops apply`; YAML with typo'd apiVersion causing codec to return an unstructured/unknown type; mixing Kubernetes-native manifests (Deployment etc.) into the kops config file.

Related errors


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