kubernetes/kops · error

error reading cluster configuration %q: %v

Error message

error reading cluster configuration %q: %v

What it means

ClusterVFS.find found a config file at basePath/<name>/pki/cluster but readConfig failed with a non-IsNotExist error (parse failure, permission, backend error). Not-exist is treated as 'cluster absent' (nil,nil), so this error means the cluster exists but its config could not be read/decoded.

Source

Thrown at pkg/client/simple/vfsclientset/cluster.go:194

		}
		key := strings.TrimSuffix(relativePath, "/config")
		keys = append(keys, key)
	}
	return keys, nil
}

func (r *ClusterVFS) find(ctx context.Context, clusterName string) (*api.Cluster, error) {
	if clusterName == "" {
		return nil, fmt.Errorf("clusterName is required")
	}
	configPath := r.basePath.Join(clusterName, registry.PathCluster)

	o, err := r.readConfig(ctx, configPath)
	if err != nil {
		if os.IsNotExist(err) {
			return nil, nil
		}
		return nil, fmt.Errorf("error reading cluster configuration %q: %v", clusterName, err)
	}

	c := o.(*api.Cluster)

	if c.ObjectMeta.Name == "" {
		c.ObjectMeta.Name = clusterName
	}
	if c.ObjectMeta.Name != clusterName {
		klog.Warningf("Name of cluster does not match: actual name was %q, but cluster name was %q (using registry path %v).", c.ObjectMeta.Name, clusterName, registry.PathCluster)
	}

	// TODO: Split this out into real version updates / schema changes
	if c.Spec.ConfigStore.Base == "" {
		configBase, err := r.configBase(clusterName)
		if err != nil {
			return nil, fmt.Errorf("error building ConfigStore.Base for cluster: %v", err)
		}
		c.Spec.ConfigStore.Base = configBase.Path()

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Inspect the wrapped %v cause to distinguish decode vs permission vs backend error
  2. Restore the cluster config from backup or re-create the cluster config (kops replace/get --full to compare)
  3. Upgrade/downgrade kops so the store schema version matches the binary
  4. Fix bucket/object permissions on basePath/<name>/pki/cluster
Defensive patterns

Strategy: try-catch

Validate before calling

// check the config object exists and is readable before full parse
p := basePath.Join(name, registry.PathCluster)
data, err := p.ReadFile()
if err != nil { return err }
if len(bytes.TrimSpace(data)) == 0 {
	return fmt.Errorf("cluster config for %q is empty/corrupt", name)
}

Try / catch

cluster, err := clusterVFS.Get(ctx, name, metav1.GetOptions{})
if err != nil && strings.Contains(err.Error(), "error reading cluster configuration") {
	// distinguish corrupt config from transient backend error
	if _, rerr := configPath.ReadFile(); rerr == nil {
		return fmt.Errorf("cluster config for %q is corrupt or undecodable; restore from backup", name)
	}
	return fmt.Errorf("transient backend error reading %q: %w", name, err)
}

Prevention

When it happens

Trigger: Corrupted or partially-written cluster config in the state store; unsupported schema/store version; permission denied on the object; transient backend errors.

Common situations: Interrupted kops create leaving truncated YAML/JSON; manually edited cluster config; state store written by a newer kops with a schema the current binary cannot decode; object-lock/permission changes on the bucket.

Related errors


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