kubernetes/kops · error

error reading Keyset %q: %v

Error message

error reading Keyset %q: %v

What it means

This error is returned by ClientsetSecretStore.DeleteSecret when the Get call for the Keyset fails with an error other than NotFound (NotFound is deliberately treated as success). It wraps the underlying client-go error, so the cause (forbidden, timeout, connection refused) is in the %v text. It means the delete could not even verify the keyset's existence or read its type before deleting.

Source

Thrown at upup/pkg/fi/secrets/clientset_secretstore.go:158

	}
	if s == nil {
		return nil, fmt.Errorf("Secret not found: %q", name)
	}
	return s, nil
}

// DeleteSecret implements fi.SecretStore::DeleteSecret
func (c *ClientsetSecretStore) DeleteSecret(name string) error {
	ctx := context.TODO()

	client := c.clientset.Keysets(c.namespace)

	keyset, err := client.Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		if errors.IsNotFound(err) {
			return nil
		}
		return fmt.Errorf("error reading Keyset %q: %v", name, err)
	}

	if keyset.Spec.Type != kops.SecretTypeSecret {
		return fmt.Errorf("mismatch on Keyset type on %q", name)
	}

	if err := client.Delete(ctx, name, metav1.DeleteOptions{}); err != nil {
		return fmt.Errorf("error deleting Keyset %q: %v", name, err)
	}

	return nil
}

// GetOrCreateSecret implements fi.SecretStore::GetOrCreateSecret
func (c *ClientsetSecretStore) GetOrCreateSecret(ctx context.Context, name string, secret *fi.Secret) (*fi.Secret, bool, error) {
	for i := 0; i < 2; i++ {
		s, err := c.FindSecret(name)
		if err != nil {

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Read the wrapped error to identify the root cause (forbidden vs timeout vs connection)
  2. Verify RBAC allows get (and delete) on keysets in the target namespace
  3. Check API server reachability: kubectl get keysets -n <namespace> <name>
  4. Retry after connectivity is restored — deletion is safe to re-run because NotFound is treated as success
  5. Confirm the correct cluster/namespace before retrying

Example fix

// before: single attempt fails on transient errors
if err := store.DeleteSecret("admin"); err != nil { return err }
// after: retry transient failures; NotFound is already a no-op
var lastErr error
for i := 0; i < 3; i++ {
    err := store.DeleteSecret("admin")
    if err == nil { return nil }
    lastErr = err
    if strings.Contains(err.Error(), "forbidden") { return err }
    time.Sleep(time.Duration(i+1) * time.Second)
}
return lastErr
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: confirm get access on the keyset before deleting
client := clientset.Keysets(namespace)
if _, err := client.Get(context.TODO(), NamePrefix+name, metav1.GetOptions{}); err != nil {
    if errors.IsNotFound(err) { return nil } // already gone
    return fmt.Errorf("preflight get failed: %v", err)
}

Type guard

func isTransientAPIError(err error) bool {
    return err != nil && !errors.IsNotFound(err) && !errors.IsForbidden(err)
}

Try / catch

err := store.DeleteSecret(name)
if err != nil && strings.Contains(err.Error(), "error reading Keyset") {
    for i := 0; i < 3; i++ {
        time.Sleep(time.Duration(1<<i) * time.Second)
        if err = store.DeleteSecret(name); err == nil { break }
    }
}
if err != nil { return err }

Prevention

When it happens

Trigger: DeleteSecret(name) calls client.Get(ctx, name, metav1.GetOptions{}); the API server returns a non-NotFound error — RBAC denial on keysets/get, API server unreachable, request timeout, or invalid name rejected by validation.

Common situations: Running `kops delete secret` with a ServiceAccount lacking get permission on keysets; API server temporarily down; wrong namespace configured; network/VPN interruption during automation.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


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