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

  1. Inspect the tree entries logged in the error message (%s of tree[i].Path()) to find the offending non-S3 path
  2. Ensure the entire tree under the S3 prefix is served by the same S3VFS/ filesystem instance
  3. Fix any custom Path implementation so ReadTree returns only *S3Path objects for an S3 root
  4. 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

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


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