{"record":{"id":"b7b35d4167831b4b","repo":"kubernetes/kops","slug":"server-side-client-does-not-support-mirrorto","errorCode":null,"errorMessage":"server-side client does not support MirrorTo","messagePattern":"server-side client does not support MirrorTo","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/kops-controller/pkg/server/keystore.go","lineNumber":70,"sourceCode":"}\n\n// FindKeyset finds a Keyset.  If the keyset is not found, it returns (nil, nil).\nfunc (k *keystore) FindKeyset(ctx context.Context, name string) (*fi.Keyset, error) {\n\tkeySet, ok := k.keySets[name]\n\tif !ok {\n\t\treturn nil, nil\n\t}\n\treturn keySet, nil\n}\n\n// StoreKeyset writes a Keyset to the store.\nfunc (k *keystore) StoreKeyset(ctx context.Context, name string, keyset *fi.Keyset) error {\n\treturn fmt.Errorf(\"server-side client does not support StoreKeyset\")\n}\n\n// MirrorTo will copy secrets to a vfs.Path, which is often easier for a machine to read\nfunc (k *keystore) MirrorTo(ctx context.Context, basedir vfs.Path) error {\n\treturn fmt.Errorf(\"server-side client does not support MirrorTo\")\n}\n\n// ListKeysets will return all the KeySets.\nfunc (k *keystore) ListKeysets() (map[string]*fi.Keyset, error) {\n\treturn nil, fmt.Errorf(\"server-side client does not support ListKeysets\")\n}\n\nfunc newKeystore(basePath string, cas []string) (*keystore, map[string]string, error) {\n\tkeystore := &keystore{\n\t\tkeys:    map[string]keystoreEntry{},\n\t\tkeySets: map[string]*fi.Keyset{},\n\t}\n\tfor _, name := range cas {\n\t\tcertBytes, err := os.ReadFile(path.Join(basePath, name+\".crt\"))\n\t\tif err != nil {\n\t\t\treturn nil, nil, fmt.Errorf(\"reading %q certificate: %v\", name, err)\n\t\t}\n\t\t// TODO: Support multiple certificates?","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/cmd/kops-controller/pkg/server/keystore.go#L52-L88","documentation":"MirrorTo copies keystore secrets to a vfs.Path for machine consumption; the server-side kops-controller keystore does not implement it and always returns this stub error, because mirroring secrets is a client-side/operator concern, not something the in-memory server store supports.","triggerScenarios":"Any call to keystore.MirrorTo on the server-side keystore — e.g. code that renders/mirrors keystore contents to a vfs path (such as nodeup/protokube style MirrorTo flows) reaching the Render path that uses this store.","commonSituations":"Running code that normally mirrors secrets from the cluster CA store inside the controller; template/render code (Render) invoking MirrorTo against the read-only server keystore.","solutions":["Avoid MirrorTo on the server-side keystore; use the cluster/vfs-backed keystore for mirroring","If a mirror target is required in the controller, load the needed material directly from the controller's PKI basePath files","Handle the error explicitly and skip mirroring when running server-side"],"exampleFix":"// before\nerr := ks.MirrorTo(ctx, vfsPath)\n\n// after\nif err := ks.MirrorTo(ctx, vfsPath); err != nil && strings.Contains(err.Error(), \"does not support MirrorTo\") {\n\t// server-side store: read required material from basePath instead\n}","handlingStrategy":"validation","validationCode":"// Skip mirroring when operating against the server-side keystore\nif isServerSideKeystore(ks) {\n\tklog.V(2).Infof(\"skipping MirrorTo: server-side keystore does not support mirroring\")\n\treturn nil\n}","typeGuard":"func isServerSideKeystore(store pki.Keystore) bool {\n\t_, ro := store.(interface{ ListKeysets() (map[string]*fi.Keyset, error) })\n\treturn ro\n}","tryCatchPattern":"if err := ks.MirrorTo(ctx, basedir); err != nil {\n\tif strings.Contains(err.Error(), \"does not support MirrorTo\") {\n\t\treturn mirrorFromPKIDir(ctx, basePath, basedir) // copy files directly\n\t}\n\treturn err\n}","preventionTips":["Only call MirrorTo on the cluster/vfs-backed keystore","Server-side, read material directly from the controller's PKI basePath files","Gate mirroring code paths behind a capability check on the store","Document the server keystore as read-only in code comments and design docs"],"tags":["keystore","read-only","unsupported-operation","vfs"],"backgroundTag":"unsupported-operation","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}