kubernetes/kops · error
must specify %q label with cluster name to replace SSHCreden
Error message
must specify %q label with cluster name to replace SSHCredential
What it means
When replacing an SSHCredential object, `kops replace` derives the target cluster from the metadata label `kops.k8s.io/cluster` (kopsapi.LabelClusterName). The manifest lacks that label, so the command cannot determine which cluster's SSH credential store to write to and aborts.
Source
Thrown at cmd/kops/replace.go:200
}
}
switch ig {
case nil:
klog.Infof("instanceGroup: %v was not found, creating resource now", igName)
_, err = clientset.InstanceGroupsFor(cluster).Create(ctx, v, metav1.CreateOptions{})
if err != nil {
return fmt.Errorf("error creating instanceGroup: %v", err)
}
default:
_, err = clientset.InstanceGroupsFor(cluster).Update(ctx, v, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("error replacing instanceGroup: %v", err)
}
}
case *kopsapi.SSHCredential:
clusterName := v.ObjectMeta.Labels[kopsapi.LabelClusterName]
if clusterName == "" {
return fmt.Errorf("must specify %q label with cluster name to replace SSHCredential", kopsapi.LabelClusterName)
}
if v.Spec.PublicKey == "" {
return fmt.Errorf("spec.PublicKey is required")
}
cluster, err := clientset.GetCluster(ctx, clusterName)
if err != nil {
return err
}
sshCredentialStore, err := clientset.SSHCredentialStore(cluster)
if err != nil {
return err
}
sshKeyArr := []byte(v.Spec.PublicKey)
err = sshCredentialStore.AddSSHPublicKey(ctx, sshKeyArr)
if err != nil {View on GitHub (pinned to 4c8573c808)
Solutions
- Add the label to the manifest: `metadata.labels.kops.k8s.io: <cluster-name>` (the exact kops.k8s.io/cluster key).
- Or export an existing correct manifest with `kops get sshpublickey <cluster> -o yaml` as a template.
- Specify the cluster on the command line (`kops replace -f ssh.yaml --name <cluster>`) where supported, so other fields are validated against the right cluster.
Example fix
# before
metadata:
name: admin
# after
metadata:
name: admin
labels:
kops.k8s.io/cluster: mycluster.example.com Defensive patterns
Strategy: validation
Validate before calling
func validateSSHCred(manifest map[string]interface{}) error {
meta, _ := manifest["metadata"].(map[string]interface{})
labels, _ := meta["labels"].(map[string]interface{})
if labels["kops.k8s.io/cluster"] == "" {
return fmt.Errorf("manifest must set metadata.labels.kops.k8s.io/cluster")
}
return nil
} Prevention
- Always include the kops.k8s.io/cluster label in SSHCredential manifests
- Generate manifests from `kops get sshpublickey -o yaml` rather than hand-writing
- Lint kops manifests in CI for required labels
- Never strip labels when copying manifests between clusters
When it happens
Trigger: Applying an SSHCredential YAML that has no `metadata.labels.kops.k8s.io/cluster: <clustername>` entry, e.g. a hand-written manifest or one exported from a source that stripped labels.
Common situations: Hand-authoring an SSH credential manifest from documentation examples; copying a manifest between clusters and removing/renaming labels; exporting with a tool that drops metadata labels.
Related errors
- spec.PublicKey is required
- failed to annotate %q: %w
- expected exactly one object in manifest %s, found %d
- failed to parse objects: %w
- failed to parse apiVersion %q
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/ea6fb916e4a4ff70.
Report an issue: GitHub.