kubernetes/kops · error
invalid path in s3fs tree: %s
Error message
invalid path in s3fs tree: %s
What it means
RemoveAll gathers the tree of objects under a prefix via ReadTree, then batch-deletes them. Every entry in the tree must be an *S3Path; if a tree entry is any other vfs.Path implementation, this error is thrown because S3 batch delete can only build ObjectIdentifiers from S3 keys.
Source
Thrown at util/pkg/vfs/s3fs.go:145
return nil
}
func (p *S3Path) RemoveAll(ctx context.Context) error {
client, err := p.client(ctx)
if err != nil {
return err
}
tree, err := p.ReadTree(ctx)
if err != nil {
return err
}
objects := make([]types.ObjectIdentifier, len(tree))
for i := range tree {
s3Object, isS3Object := tree[i].(*S3Path)
if !isS3Object {
return fmt.Errorf("invalid path in s3fs tree: %s", tree[i].Path())
}
objects[i] = types.ObjectIdentifier{
Key: aws.String(s3Object.key),
}
}
klog.V(8).Infof("removing all file in %s", p)
request := &s3.DeleteObjectsInput{
Bucket: aws.String(p.bucket),
Delete: &types.Delete{},
}
for len(objects) > 0 {
// DeleteObjects can only process 1000 objects per call
if len(objects) > 1000 {
request.Delete.Objects = objects[:1000]View on GitHub (pinned to 4c8573c808)
Solutions
- Inspect the tree entries logged in the error message (%s of tree[i].Path()) to find the offending non-S3 path
- Ensure the entire tree under the S3 prefix is served by the same S3VFS/ filesystem instance
- Fix any custom Path implementation so ReadTree returns only *S3Path objects for an S3 root
- As a workaround, delete offending paths individually with Remove() before calling RemoveAll
Example fix
// before
for i := range tree { if _, ok := tree[i].(*S3Path); !ok { return fmt.Errorf("invalid path in s3fs tree: %s", tree[i].Path()) } }
// after (caller): keep the tree homogeneous
fs := vfs.NewS3FileSystem(...)
paths, err := fs.ReadTree(ctx, s3Path) // not a mixed FS
if err != nil { return err }
err = s3Path.RemoveAll(ctx) Defensive patterns
Strategy: type-guard
Validate before calling
paths, err := fs.ReadTree(ctx, root)
if err != nil { return err }
for _, t := range paths {
if _, ok := t.(*vfs.S3Path); !ok {
return fmt.Errorf("non-S3 path %s in tree; refusing RemoveAll", t.Path())
}
} Type guard
func isS3Path(p vfs.Path) (*vfs.S3Path, bool) {
s3p, ok := p.(*vfs.S3Path)
return s3p, ok
} Prevention
- Keep one vfs filesystem instance per backend; never mix memfs/osfs under an S3 root
- Type-assert tree entries before batch operations
- Pin kOps/vfs versions when using custom Path implementations
When it happens
Trigger: Calling RemoveAll on an S3Path whose ReadTree returns a mixed filesystem (e.g. a mounted/bridged vfs combining S3 with memfs or local paths), or a tree entry that fails the *S3Path type assertion.
Common situations: Custom vfs implementations or tests that mix path types under one tree; bugs in custom Path implementations returning non-S3 paths from a ReadTree rooted at S3.
Related errors
- error reading addons from %q: %v
- unexpected kind for cluster, got %T, want kops.Cluster
- error reading etcd manifest %s: %v
- cannot parse VFS path %q: %v
- path is not cluster readable: %v
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/ed8d5cefa24c362f.
Report an issue: GitHub.