{"record":{"id":"a8802fa7b5b65d0b","repo":"kubernetes/kops","slug":"keystore-path-is-not-cluster-readable-v","errorCode":null,"errorMessage":"keyStore path is not cluster readable: %v","messagePattern":"keyStore path is not cluster readable: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/populate_cluster_spec.go","lineNumber":189,"sourceCode":"\t}\n\n\tkeyStore, err := clientset.KeyStore(cluster)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif cluster.Spec.ConfigStore.Keypairs == \"\" {\n\t\thasVFSPath, ok := keyStore.(fi.HasVFSPath)\n\t\tif !ok {\n\t\t\t// We will mirror to ConfigBase\n\t\t\tbasedir := configBase.Join(\"pki\")\n\t\t\tcluster.Spec.ConfigStore.Keypairs = basedir.Path()\n\t\t} else if vfs.IsClusterReadable(hasVFSPath.VFSPath()) {\n\t\t\tvfsPath := hasVFSPath.VFSPath()\n\t\t\tcluster.Spec.ConfigStore.Keypairs = vfsPath.Path()\n\t\t} else {\n\t\t\t// We could implement this approach, but it seems better to get all clouds using cluster-readable storage\n\t\t\treturn fmt.Errorf(\"keyStore path is not cluster readable: %v\", hasVFSPath.VFSPath())\n\t\t}\n\t}\n\n\tsecretStore, err := clientset.SecretStore(cluster)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tif cluster.Spec.ConfigStore.Secrets == \"\" {\n\t\thasVFSPath, ok := secretStore.(fi.HasVFSPath)\n\t\tif !ok {\n\t\t\t// We will mirror to ConfigBase\n\t\t\tbasedir := configBase.Join(\"secrets\")\n\t\t\tcluster.Spec.ConfigStore.Secrets = basedir.Path()\n\t\t} else if vfs.IsClusterReadable(hasVFSPath.VFSPath()) {\n\t\t\tvfsPath := hasVFSPath.VFSPath()\n\t\t\tcluster.Spec.ConfigStore.Secrets = vfsPath.Path()\n\t\t} else {","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/populate_cluster_spec.go#L171-L207","documentation":"kops resolves the keypair store (PKI keys) location; if the store implements fi.HasVFSPath but the underlying VFS path is not cluster readable, run() rejects it. Nodes must be able to read the keypair store path during bootstrap.","triggerScenarios":"cluster.spec.configStore.keypairs is empty (so kops derives it from the KeyStore) and the KeyStore's VFS path fails vfs.IsClusterReadable — e.g. a keystore pointed at a non-cluster-accessible bucket or filesystem path.","commonSituations":"State store in a bucket that nodes cannot access via IAM; keystore relocated via configStore.keypairs to an unreadable path; environments where VFS credentials differ between CLI and nodes.","solutions":["Ensure the keypair store path is cluster readable: point it at the same cloud object store as configBase and grant nodes read IAM permissions.","Leave configStore.keypairs unset so kops mirrors PKI into configBase (under <configBase>/pki).","Check the VFS path printed in the error and verify its scheme and permissions."],"exampleFix":"# before\nconfigStore:\n  keypairs: file:///etc/kops/pki\n# after\nconfigStore:\n  keypairs: s3://my-kops-state-bucket/cluster.example.com/pki","handlingStrategy":"validation","validationCode":"if cluster.Spec.ConfigStore.Keypairs != \"\" && !strings.HasPrefix(cluster.Spec.ConfigStore.Keypairs, \"s3://\") {\n\treturn fmt.Errorf(\"keypair store path must be cluster readable\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer leaving configStore.keypairs unset so kops mirrors PKI under configBase","If overriding, use a bucket nodes can read with their instance profiles","Audit PKI location after state-store migrations"],"tags":["vfs","pki","storage-permissions"],"backgroundTag":"invalid-storage-path","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"}