kubernetes/kops · error
error creating keyset %q: %v
Error message
error creating keyset %q: %v
What it means
When the Keyset does not already exist, storeKeyset calls client.Create; failure is wrapped as 'error creating keyset "<name>": <underlying>'. Most commonly this is AlreadyExists (a race with another writer) or an API/RBAC error, surfaced from upup/pkg/fi/clientset_castore.go:247 via StoreKeyset.
Source
Thrown at upup/pkg/fi/clientset_castore.go:247
oldKeyset, err := client.Get(ctx, name, metav1.GetOptions{})
if errors.IsNotFound(err) {
oldKeyset = nil
err = nil
}
if err == nil {
if oldKeyset == nil {
create = true
} else {
kopsKeyset.ObjectMeta = oldKeyset.ObjectMeta
}
} else {
return fmt.Errorf("error reading keyset %q: %v", name, err)
}
if create {
if _, err := client.Create(ctx, kopsKeyset, metav1.CreateOptions{}); err != nil {
return fmt.Errorf("error creating keyset %q: %v", name, err)
}
} else {
if _, err := client.Update(ctx, kopsKeyset, metav1.UpdateOptions{}); err != nil {
return fmt.Errorf("error updating keyset %q: %v", name, err)
}
}
return nil
}
// addSSHCredential saves the specified SSH Credential to the registry, doing an update or insert
func (c *ClientsetCAStore) addSSHCredential(ctx context.Context, publicKey string) error {
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 {View on GitHub (pinned to 4c8573c808)
Solutions
- If the wrapped error is AlreadyExists, re-run the operation so storeKeyset takes the Update path, or fetch and merge into the existing keyset
- Check RBAC allows creating keysets in the kops namespace
- Serialize rotation operations (a single kOps run) to avoid create/update races
- Inspect the underlying message for validation failures and fix the keyset payload
Example fix
// before: naive create fails on race
client.Create(ctx, kopsKeyset, metav1.CreateOptions{})
// after: tolerate race by falling back to update
if _, err := client.Create(ctx, kopsKeyset, metav1.CreateOptions{}); err != nil {
if apierrors.IsAlreadyExists(err) {
_, err = client.Update(ctx, kopsKeyset, metav1.UpdateOptions{})
}
if err != nil { return err }
} Defensive patterns
Strategy: retry
Validate before calling
// detect likely race before create
if _, err := kubeClient.Keysets(ns).Get(ctx, name, metav1.GetOptions{}); err == nil {
// keyset exists; use the update path instead of expecting create
} Type guard
func isAlreadyExists(err error) bool {
return apierrors.IsAlreadyExists(errors.Unwrap(err)) || strings.Contains(err.Error(), "AlreadyExists")
} Try / catch
err := store.StoreKeyset(ctx, name, keyset)
if err != nil {
if strings.Contains(err.Error(), "error creating keyset") && strings.Contains(err.Error(), "AlreadyExists") {
// re-run so storeKeyset takes the Update path
}
return err
} Prevention
- Run only one key-rotation process at a time to avoid create races
- Check for AlreadyExists in the wrapped error and fall back to update
- Grant create on keysets to automation identities
When it happens
Trigger: client.Create fails: the keyset was created concurrently (AlreadyExists), RBAC denies create on keysets, the object is invalid per validation, or the API server rejects the request.
Common situations: Two kOps processes rotating keys at once; service accounts lacking create permission during automation; ObjectMeta/name conflicts after manual keyset creation.
Related errors
- error reading keyset %q: %v
- error listing Keysets: %v
- error updating keyset %q: %v
- error querying namespace %q: %v
- CAPI Machine is missing cluster.x-k8s.io/deployment-name lab
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/08f9e4346d0c8f63.
Report an issue: GitHub.