kubernetes/kops · error

cluster Watch not implemented for vfs store

Error message

cluster Watch not implemented for vfs store

What it means

The vfs-backed cluster client cannot provide watch streams: VFS is a static file store with no server-side event mechanism, so Watch always returns this error. Any code that requires change notifications must poll instead.

Source

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

		if err != nil {
			return nil, fmt.Errorf("error building ConfigStore.Base for cluster: %v", err)
		}
		c.Spec.ConfigStore.Base = configBase.Path()
	}

	return c, nil
}

func (r *ClusterVFS) Delete(name string, options *metav1.DeleteOptions) error {
	return fmt.Errorf("cluster Delete not implemented for vfs store")
}

func (r *ClusterVFS) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
	return fmt.Errorf("cluster DeleteCollection not implemented for vfs store")
}

func (r *ClusterVFS) Watch(opts metav1.ListOptions) (watch.Interface, error) {
	return nil, fmt.Errorf("cluster Watch not implemented for vfs store")
}

func (r *ClusterVFS) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *api.Cluster, err error) {
	return nil, fmt.Errorf("cluster Patch not implemented for vfs store")
}

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Replace Watch with periodic polling: call List()/Find() on a ticker to detect changes.
  2. Use an API-server-backed kops client (grpc-clientset) if watch semantics are required.
  3. If implementing the client, return watch.NewEmptyWatch() style stubs plus error only where the interface forces it.

Example fix

// before
w, err := clusterClient.Watch(metav1.ListOptions{})
// after
ticker := time.NewTicker(30 * time.Second)
for range ticker.C {
    obj, err := clusterClient.List(ctx, metav1.ListOptions{})
    if err != nil { return err }
    reconcile(obj)
}
Defensive patterns

Strategy: fallback

Validate before calling

if _, ok := clusterClient.(interface{ Watch(metav1.ListOptions) (watch.Interface, error) }); !ok {
    return errors.New("watch unsupported on vfs store; use polling")
}

Type guard

func supportsWatch(c interface{}) bool {
    _, ok := c.(interface{ Watch(metav1.ListOptions) (watch.Interface, error) })
    return ok
}

Try / catch

w, err := client.Watch(opts)
if err != nil && strings.Contains(err.Error(), "not implemented for vfs store") {
    // fall back to polling List() on a ticker
}

Prevention

When it happens

Trigger: Calling ClusterVFS.Watch(opts) — e.g. informers, reflectors, or controllers expecting streaming updates on kops Cluster objects stored in VFS (S3/GCS/etc.).

Common situations: Reusing kubernetes informer/controller machinery against kops vfs clientset; code migrated from an API-server-backed client to vfs; resync loops expecting live updates.

Related errors


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