{"record":{"id":"ed8d5cefa24c362f","repo":"kubernetes/kops","slug":"invalid-path-in-s3fs-tree-s","errorCode":null,"errorMessage":"invalid path in s3fs tree: %s","messagePattern":"invalid path in s3fs tree: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/pkg/vfs/s3fs.go","lineNumber":145,"sourceCode":"\treturn nil\n}\n\nfunc (p *S3Path) RemoveAll(ctx context.Context) error {\n\tclient, err := p.client(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\ttree, err := p.ReadTree(ctx)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tobjects := make([]types.ObjectIdentifier, len(tree))\n\tfor i := range tree {\n\t\ts3Object, isS3Object := tree[i].(*S3Path)\n\t\tif !isS3Object {\n\t\t\treturn fmt.Errorf(\"invalid path in s3fs tree: %s\", tree[i].Path())\n\t\t}\n\n\t\tobjects[i] = types.ObjectIdentifier{\n\t\t\tKey: aws.String(s3Object.key),\n\t\t}\n\t}\n\n\tklog.V(8).Infof(\"removing all file in %s\", p)\n\n\trequest := &s3.DeleteObjectsInput{\n\t\tBucket: aws.String(p.bucket),\n\t\tDelete: &types.Delete{},\n\t}\n\n\tfor len(objects) > 0 {\n\t\t// DeleteObjects can only process 1000 objects per call\n\t\tif len(objects) > 1000 {\n\t\t\trequest.Delete.Objects = objects[:1000]","sourceCodeStart":127,"sourceCodeEnd":163,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/util/pkg/vfs/s3fs.go#L127-L163","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nfor i := range tree { if _, ok := tree[i].(*S3Path); !ok { return fmt.Errorf(\"invalid path in s3fs tree: %s\", tree[i].Path()) } }\n// after (caller): keep the tree homogeneous\nfs := vfs.NewS3FileSystem(...)\npaths, err := fs.ReadTree(ctx, s3Path) // not a mixed FS\nif err != nil { return err }\nerr = s3Path.RemoveAll(ctx)","handlingStrategy":"type-guard","validationCode":"paths, err := fs.ReadTree(ctx, root)\nif err != nil { return err }\nfor _, t := range paths {\n\tif _, ok := t.(*vfs.S3Path); !ok {\n\t\treturn fmt.Errorf(\"non-S3 path %s in tree; refusing RemoveAll\", t.Path())\n\t}\n}","typeGuard":"func isS3Path(p vfs.Path) (*vfs.S3Path, bool) {\n\ts3p, ok := p.(*vfs.S3Path)\n\treturn s3p, ok\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["s3","type-assertion","vfs","internal"],"backgroundTag":"invalid-path-type-in-tree","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}