kubernetes/kops · error

unhandled secret type %q: %v

Error message

unhandled secret type %q: %v

What it means

ListKeysets switches on keyset.Spec.Type; only SecretTypeKeypair is handled and SecretTypeSecret is skipped. Any other Spec.Type hits the default branch and returns 'unhandled secret type "<type>": <underlying>'. Notably the format verb references err (often nil), so the message may show '<nil>'. From upup/pkg/fi/clientset_castore.go:207.

Source

Thrown at upup/pkg/fi/clientset_castore.go:207

		if err != nil {
			return nil, fmt.Errorf("error listing Keysets: %v", err)
		}

		for i := range list.Items {
			keyset := &list.Items[i]
			switch keyset.Spec.Type {
			case kops.SecretTypeKeypair:
				item, err := parseKeyset(keyset)
				if err != nil {
					return nil, fmt.Errorf("parsing keyset %q: %w", keyset.Name, err)
				}

				items[keyset.Name] = item

			case kops.SecretTypeSecret:
				continue // Ignore - this is handled by ClientsetSecretStore
			default:
				return nil, fmt.Errorf("unhandled secret type %q: %v", keyset.Spec.Type, err)
			}
		}
	}

	return items, nil
}

// StoreKeyset implements CAStore::StoreKeyset
func (c *ClientsetCAStore) StoreKeyset(ctx context.Context, name string, keyset *Keyset) error {
	return c.storeKeyset(ctx, name, keyset)
}

// storeKeyset saves the specified keyset to the registry.
func (c *ClientsetCAStore) storeKeyset(ctx context.Context, name string, keyset *Keyset) error {
	create := false
	client := c.clientset.Keysets(c.namespace)

	kopsKeyset, err := keyset.ToAPIObject(name)

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect kubectl get keysets -n <namespace> -o jsonpath='{.items[*].spec.type}' to find the offending object
  2. Delete or correct the object with the unrecognized spec.type (or move it out of the kops namespace)
  3. Upgrade kOps to a version that knows the new keyset type instead of downgrading
  4. Patch ListKeysets to ignore unknown types (continue) rather than erroring if upstream allows

Example fix

// before
default:
	return nil, fmt.Errorf("unhandled secret type %q: %v", keyset.Spec.Type, err)
// after
default:
	klog.Warningf("skipping keyset %q with unhandled type %q", keyset.Name, keyset.Spec.Type)
	continue
Defensive patterns

Strategy: type-guard

Validate before calling

types := map[string]bool{"keypair": true, "secret": true}
for _, ks := range allKeysets {
	if !types[string(ks.Spec.Type)] {
		return fmt.Errorf("keyset %s has unsupported type %q", ks.Name, ks.Spec.Type)
	}
}

Type guard

func isKnownKeysetType(t kops.SecretType) bool {
	return t == kops.SecretTypeKeypair || t == kops.SecretTypeSecret
}

Try / catch

items, err := store.ListKeysets()
if err != nil {
	if strings.Contains(err.Error(), "unhandled secret type") {
		// version mismatch: upgrade kOps or clean stray keysets
	}
	return err
}

Prevention

When it happens

Trigger: A Keyset object exists in the namespace whose Spec.Type is neither 'keypair' nor 'secret' — e.g. a type introduced by a newer kOps version, or a hand-created object with a wrong/empty type.

Common situations: Rolling back kOps after an upgrade introduced new keyset types; operators copying Keyset YAML by hand with a modified type field; CRD objects from other tooling sharing the namespace.

Related errors


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