kubernetes/kops · error
error creating SSHCredential: %v
Error message
error creating SSHCredential: %v
What it means
addSSHCredential creates the 'admin' SSHCredential via client.Create when no existing object was found. Any Create failure is wrapped as 'error creating SSHCredential: %v'. It means the API server refused to persist the new SSH credential object.
Source
Thrown at upup/pkg/fi/clientset_castore.go:277
create := false
client := c.clientset.SSHCredentials(c.namespace)
sshCredential, err := client.Get(ctx, "admin", metav1.GetOptions{})
if err != nil {
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
}View on GitHub (pinned to 4c8573c808)
Solutions
- If the cause is AlreadyExists, re-run the command so it takes the Update path
- Check RBAC allows create on sshcredentials.kops.k8s.io
- Verify the kops namespace exists in the cluster
- Check admission webhooks/quotas if the cause is a rejection other than auth
Example fix
// before
if err := store.AddSSHPublicKey(ctx, pub); err != nil { return err }
// after (handle create-vs-exists race)
if err := store.AddSSHPublicKey(ctx, pub); err != nil {
if strings.Contains(err.Error(), "already exists") {
return nil // another writer created it; update happens on next run
}
return err
} Defensive patterns
Strategy: retry
Validate before calling
// confirm namespace exists and you can read credentials
if err := clientset.SSHCredentials(ns).Delete(ctx, "__probe__", metav1.DeleteOptions{}); err != nil && !apierrors.IsNotFound(err) && !apierrors.IsForbidden(err) {
return fmt.Errorf("api access problem: %w", err)
} Type guard
func isAlreadyExists(err error) bool { return apierrors.IsAlreadyExists(err) } Try / catch
if err := store.AddSSHPublicKey(ctx, pub); err != nil {
if isAlreadyExists(err) { return nil } // concurrent creator won; update next run
return err
} Prevention
- Do not run concurrent `kops create sshpublickey` for the same cluster
- Check the wrapped cause for AlreadyExists and switch to the update path
- Ensure the kops namespace exists before first write
- Grant create on sshcredentials.kops.k8s.io
When it happens
Trigger: First AddSSHPublicKey call for a cluster where the credential does not exist and Create fails: AlreadyExists race (another process created it), RBAC denial on create, invalid object/namespace, or API server error.
Common situations: Concurrent `kops create sshpublickey` invocations racing to create the same 'admin' credential; restricted service account; quota/admission webhooks rejecting the object.
Related errors
- error reading SSHCredential: %v
- error updating 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/967a880c4ca6a584.
Report an issue: GitHub.