kubernetes/kops · error

server-side client does not support StoreKeyset

Error message

server-side client does not support StoreKeyset

What it means

The server-side keystore in kops-controller is a read-only, in-memory implementation of pki.Keystore/fi.CAStore. StoreKeyset is part of the interface it must satisfy, but persisting new keysets is intentionally unsupported in the controller process, so the method unconditionally returns this stub error.

Source

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

	entry, ok := k.keys[name]
	if !ok {
		return nil, nil, fmt.Errorf("unknown CA %q", name)
	}
	return entry.certificate, entry.key, nil
}

// FindKeyset finds a Keyset.  If the keyset is not found, it returns (nil, nil).
func (k *keystore) FindKeyset(ctx context.Context, name string) (*fi.Keyset, error) {
	keySet, ok := k.keySets[name]
	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 {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Do not call StoreKeyset on the server-side keystore; persist keysets through the cluster's regular keystore instead
  2. If keyset writing is needed in the controller, use a store implementation backed by the cluster state (e.g. vfs-based CAStore)
  3. Refactor caller to treat the server keystore as read-only and handle the not-supported error explicitly

Example fix

// before
err := serverKeystore.StoreKeyset(ctx, name, keyset)

// after
if err := serverKeystore.StoreKeyset(ctx, name, keyset); err != nil {
	// persist via cluster store instead
	err = clusterStore.Keystore().StoreKeyset(ctx, name, keyset)
}
Defensive patterns

Strategy: validation

Validate before calling

// Detect the read-only server keystore before attempting a write
type readOnlyKeystore interface{ StoreKeyset(ctx context.Context, name string, ks *fi.Keyset) error }
if _, ok := store.(readOnlyKeystore); ok && isServerSideKeystore(store) {
	return fmt.Errorf("refusing StoreKeyset on read-only server-side keystore")
}

Type guard

func isServerSideKeystore(store pki.Keystore) bool {
	_, ro := store.(interface{ MirrorTo(ctx context.Context, p vfs.Path) error })
	return ro // server keystore is the only impl lacking write support markers
}

Try / catch

if err := ks.StoreKeyset(ctx, name, keyset); err != nil {
	if strings.Contains(err.Error(), "does not support StoreKeyset") {
		return persistViaClusterStore(ctx, name, keyset)
	}
	return err
}

Prevention

When it happens

Trigger: Any code path that calls keystore.StoreKeyset on the server-side keystore — e.g. PKI issue/rotate logic that expects a writable store (like the vfs/cluster-based CAStore) is invoked inside kops-controller.

Common situations: Reusing kops-controller server code with a component that tries to write generated or rotated keysets back to the store; a code refactor routes keyset persistence through the server keystore instead of the cluster store.

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/f7c19863754d41d8. Report an issue: GitHub.