kubernetes/kops · error

server-side client does not support ListKeysets

Error message

server-side client does not support ListKeysets

What it means

ListKeysets enumerates all keysets in a store; the server-side kops-controller keystore only loads a fixed, preconfigured set of CAs into memory and cannot enumerate the cluster's full keyset list, so it returns this stub error unconditionally.

Source

Thrown at cmd/kops-controller/pkg/server/keystore.go:75

	if !ok {
		return nil, nil
	}
	return keySet, nil
}

// StoreKeyset writes a Keyset to the store.
func (k *keystore) StoreKeyset(ctx context.Context, name string, keyset *fi.Keyset) error {
	return fmt.Errorf("server-side client does not support StoreKeyset")
}

// MirrorTo will copy secrets to a vfs.Path, which is often easier for a machine to read
func (k *keystore) MirrorTo(ctx context.Context, basedir vfs.Path) error {
	return fmt.Errorf("server-side client does not support MirrorTo")
}

// ListKeysets will return all the KeySets.
func (k *keystore) ListKeysets() (map[string]*fi.Keyset, error) {
	return nil, fmt.Errorf("server-side client does not support ListKeysets")
}

func newKeystore(basePath string, cas []string) (*keystore, map[string]string, error) {
	keystore := &keystore{
		keys:    map[string]keystoreEntry{},
		keySets: map[string]*fi.Keyset{},
	}
	for _, name := range cas {
		certBytes, err := os.ReadFile(path.Join(basePath, name+".crt"))
		if err != nil {
			return nil, nil, fmt.Errorf("reading %q certificate: %v", name, err)
		}
		// TODO: Support multiple certificates?
		certificate, err := pki.ParsePEMCertificate(certBytes)
		if err != nil {
			return nil, nil, fmt.Errorf("parsing %q certificate: %v", name, err)
		}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Use the cluster's vfs/etcd-backed keystore for listing all keysets instead of the server-side keystore
  2. If only the served CAs are needed, use the keypair IDs / keySets loaded at startup rather than ListKeysets
  3. Handle the not-supported error explicitly in callers that may run server-side

Example fix

// before
keysets, err := ks.ListKeysets()

// after
keysets, err := clusterKeystore.ListKeysets() // cluster-backed store
// or, server-side: iterate k.keypairIDs / loaded keySets directly
Defensive patterns

Strategy: validation

Validate before calling

// Only enumerate keysets on stores that support it; derive served CAs from config otherwise
if isServerSideKeystore(ks) {
	keysets := servedKeysetsFromConfig(keypairIDs) // map from loaded keypair-ids.yaml
	return keysets, nil
}

Type guard

type fullKeysetLister interface{ ListKeysets() (map[string]*fi.Keyset, error) }
func supportsListKeysets(s pki.Keystore) bool {
	_, ok := s.(fullKeysetLister)
	return ok && !isServerSideKeystore(s)
}

Try / catch

keysets, err := ks.ListKeysets()
if err != nil {
	if strings.Contains(err.Error(), "does not support ListKeysets") {
		return enumerateLoadedKeysets(ks), nil
	}
	return nil, err
}

Prevention

When it happens

Trigger: Any call to keystore.ListKeysets on the server-side keystore, e.g. code paths that audit or list all keysets assuming a full CAStore implementation.

Common situations: Operations/UI code listing all CAs routed against the controller's in-memory store; tests or tooling reusing the server keystore where a complete store is expected.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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