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

  1. Re-run the command — a fresh Get updates the resourceVersion and usually resolves conflicts
  2. Serialize SSH key changes (avoid concurrent writers to the same cluster)
  3. Check RBAC grants update on sshcredentials.kops.k8s.io
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/064c727a9e3cc9bc. Report an issue: GitHub.