kubernetes/kops · error
ResourceVersion not supported in ClusterVFS::Get
Error message
ResourceVersion not supported in ClusterVFS::Get
What it means
ClusterVFS::Get is the VFS-backed implementation of the cluster store's Get. It does not support the ResourceVersion field of metav1.GetOptions, so any caller passing a non-empty ResourceVersion gets this error before any I/O happens. ResourceVersion semantics (watch/optimistic-concurrency reads) are a real API-server feature the VFS backend does not emulate.
Source
Thrown at pkg/client/simple/vfsclientset/cluster.go:52
api "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/registry"
"k8s.io/kops/pkg/apis/kops/validation"
"k8s.io/kops/util/pkg/vfs"
)
type ClusterVFS struct {
VFSClientBase
}
func newClusterVFS(vfsContext *vfs.VFSContext, basePath vfs.Path) *ClusterVFS {
c := &ClusterVFS{}
c.Init("Cluster", vfsContext, basePath, StoreVersion)
return c
}
func (c *ClusterVFS) Get(ctx context.Context, name string, options metav1.GetOptions) (*api.Cluster, error) {
if options.ResourceVersion != "" {
return nil, fmt.Errorf("ResourceVersion not supported in ClusterVFS::Get")
}
o, err := c.find(ctx, name)
if err != nil {
return nil, err
}
if o == nil {
return nil, errors.NewNotFound(schema.GroupResource{Group: api.GroupName, Resource: "Cluster"}, name)
}
return o, nil
}
// Deprecated, but we need this for now..
func (c *ClusterVFS) configBase(clusterName string) (vfs.Path, error) {
if clusterName == "" {
return nil, fmt.Errorf("clusterName is required")
}
configPath := c.basePath.Join(clusterName)
return configPath, nilView on GitHub (pinned to 4c8573c808)
Solutions
- Pass a zero-value metav1.GetOptions{} (no ResourceVersion) to ClusterVFS.Get
- Strip or reset options.ResourceVersion before calling Get when reusing options from another client
- If you need ResourceVersion semantics, use a real API-server clientset instead of the VFS store
Example fix
// before
o, err := clusterVFS.Get(ctx, "prod.example.com", metav1.GetOptions{ResourceVersion: "12345"})
// after
o, err := clusterVFS.Get(ctx, "prod.example.com", metav1.GetOptions{}) Defensive patterns
Strategy: validation
Validate before calling
if options.ResourceVersion != "" {
return fmt.Errorf("vfs clientset does not support ResourceVersion in Get")
}
cluster, err := clusterVFS.Get(ctx, name, options) Type guard
func getOptionsSafeForVFS(o metav1.GetOptions) bool {
return o.ResourceVersion == ""
} Try / catch
cluster, err := clusterVFS.Get(ctx, name, metav1.GetOptions{})
if err != nil {
if strings.Contains(err.Error(), "ResourceVersion not supported") {
// retry with zero-value options
cluster, err = clusterVFS.Get(ctx, name, metav1.GetOptions{})
}
if err != nil {
return err
}
} Prevention
- Always pass metav1.GetOptions{} to VFS-backed stores
- Never copy GetOptions from client-go clients into the vfs clientset
- Add a unit test asserting Get works with zero-value options
When it happens
Trigger: Calling ClusterVFS.Get(ctx, name, metav1.GetOptions{ResourceVersion: "..."}) with any non-empty ResourceVersion string, e.g. copying GetOptions from a real clientset call or from generated client code.
Common situations: Code refactored from a kubernetes/client-go typed client to the simple VFS clientset; copied options structs that default-populate ResourceVersion; tests that set ResourceVersion to '0' or a real version string.
Related errors
- ReadOnlyError
- unexpected kind for cluster, got %T, want kops.Cluster
- method ConfigBaseFor not supported in server-side client
- ResourceVersion not supported in InstanceGroupVFS::Get
- error loading secret %q: %w
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/a865ce0b300fc95d.
Report an issue: GitHub.