juicedata/juicefs · error
%s is non-empty directory
Error message
%s is non-empty directory
What it means
webdav.Delete refuses to remove a collection (directory) that still contains entries. It PROPFINDs the target; if not found it's already gone, but if entries exist it returns "<key> is non-empty directory" instead of recursing.
Source
Thrown at pkg/object/webdav.go:102
func (w *webdav) Delete(ctx context.Context, key string, getters ...AttrGetter) error {
info, err := w.c.Stat(key)
if gowebdav.IsErrNotFound(err) {
return nil
}
if err != nil {
return err
}
if info.IsDir() {
infos, err := w.c.ReadDir(key)
if err != nil {
if gowebdav.IsErrNotFound(err) {
return nil
}
return err
}
if len(infos) != 0 {
return fmt.Errorf("%s is non-empty directory", key)
}
}
return w.c.Remove(key)
}
func (w *webdav) Copy(ctx context.Context, dst, src string) error {
return w.c.Copy(src, dst, true)
}
type webDAVFile struct {
os.FileInfo
name string
}
func (w webDAVFile) Name() string {
return w.name
}
View on GitHub (pinned to c9a67b23e8)
Solutions
- Empty the directory first (delete children), then delete the directory
- Use a recursive delete at the application level before calling Delete
- Check the server's PROPFIND result — some servers return phantom entries; verify real children exist
- If the directory is actually empty, the listing may be stale — retry
Example fix
// before
store.Delete(ctx, "photos/")
// after
objs, _ := store.List(ctx, "photos/", "", -1, true)
for _, o := range objs { store.Delete(ctx, o.Key()) }
store.Delete(ctx, "photos/") Defensive patterns
Strategy: fallback
Validate before calling
func dirEmpty(ctx context.Context, w object.ObjectStorage, key string) (bool, error) {
objs, _, err := w.List(ctx, key, "", 1, true)
if err != nil { return false, err }
return len(objs) == 0, nil
} Try / catch
err := store.Delete(ctx, key)
if err != nil && strings.HasSuffix(err.Error(), "is non-empty directory") {
// list children, delete each, then delete the directory
} Prevention
- Delete children before deleting a directory key
- Treat keys ending in '/' as collections and recurse
- Verify the bucket/volume really contains the expected children
When it happens
Trigger: Deleting a WebDAV directory path that has children; also hit during garbage collection or cleanup operations that walk keys resembling directories.
Common situations: Deleting a 'folder-like' object left by another client; mount point cleanup where empty-dir detection disagrees (server returns implicit entries); keys ending in '/' that other clients populated.
Related errors
- delete failed: %s
- delete not existed: %v
- deleting a non-existent object returns an error %v
- Invalid endpoint %s: %s
- ceph: can't put empty file
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/cb33fe8d1a58ca95.
Report an issue: GitHub.