kubernetes/kops · error
error updating SSHCredential: %v
Error message
error updating SSHCredential: %v
What it means
addSSHCredential updates the existing 'admin' SSHCredential via client.Update when it already exists. Any Update failure is wrapped as 'error updating SSHCredential: %v'. Typical cause is a resourceVersion conflict or RBAC denial.
Source
Thrown at upup/pkg/fi/clientset_castore.go:281
if errors.IsNotFound(err) {
sshCredential = nil
} else {
return fmt.Errorf("error reading SSHCredential: %v", err)
}
}
if sshCredential == nil {
sshCredential = &kops.SSHCredential{}
sshCredential.Name = "admin"
create = true
}
sshCredential.Spec.PublicKey = publicKey
if create {
if _, err := client.Create(ctx, sshCredential, metav1.CreateOptions{}); err != nil {
return fmt.Errorf("error creating SSHCredential: %v", err)
}
} else {
if _, err := client.Update(ctx, sshCredential, metav1.UpdateOptions{}); err != nil {
return fmt.Errorf("error updating SSHCredential: %v", err)
}
}
return nil
}
// deleteSSHCredential deletes the SSHCredential from the registry.
func (c *ClientsetCAStore) deleteSSHCredential(ctx context.Context) error {
client := c.clientset.SSHCredentials(c.namespace)
err := client.Delete(ctx, "admin", metav1.DeleteOptions{})
if err != nil {
return fmt.Errorf("error deleting SSHCredential: %v", err)
}
return nil
}
// AddSSHPublicKey implements CAStore::AddSSHPublicKey
func (c *ClientsetCAStore) AddSSHPublicKey(ctx context.Context, pubkey []byte) error {
_, _, _, _, err := ssh.ParseAuthorizedKey(pubkey)View on GitHub (pinned to 4c8573c808)
Solutions
- Re-run the command — a fresh Get updates the resourceVersion and usually resolves conflicts
- Serialize SSH key changes (avoid concurrent writers to the same cluster)
- Check RBAC grants update on sshcredentials.kops.k8s.io
- If persistently failing, delete and re-add the credential
Example fix
// before
client.Update(ctx, sshCredential, metav1.UpdateOptions{})
// after (retry-on-conflict at caller level)
for i := 0; i < 3; i++ {
if err := store.AddSSHPublicKey(ctx, pub); err == nil {
break
} else if !strings.Contains(err.Error(), "conflict") {
return err
}
time.Sleep(time.Duration(i+1) * time.Second)
} Defensive patterns
Strategy: retry
Validate before calling
// re-read to refresh resourceVersion before updating
_, err := clientset.SSHCredentials(ns).Get(ctx, "admin", metav1.GetOptions{})
if err != nil { return err } Type guard
func isConflict(err error) bool { return apierrors.IsConflict(err) } Try / catch
for i := 0; i < 3; i++ {
err := store.AddSSHPublicKey(ctx, pub)
if err == nil || !isConflict(err) { return err }
time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
}
return nil Prevention
- Serialize SSH credential writes; avoid parallel kops runs
- Always re-Get before Update so resourceVersion is fresh
- Check the wrapped cause for 'the object has been modified' conflicts
- Grant update on sshcredentials.kops.k8s.io
When it happens
Trigger: AddSSHPublicKey called when the 'admin' SSHCredential exists and client.Update fails: stale resourceVersion (concurrent modification), Forbidden by RBAC, or API server/etcd errors.
Common situations: Two operators running `kops create sshpublickey` simultaneously; automation rewriting the object between Get and Update; service account lacking update permission.
Related errors
- error reading SSHCredential: %v
- error creating SSHCredential: %v
- error deleting SSHCredential: %v
- error listing SSHCredentials: %v
- error adding needs-update label: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/064c727a9e3cc9bc.
Report an issue: GitHub.