AlistGo/alist · error
file exists
Error message
file exists
What it means
MakeDir checks whether the path to create already exists; if an existing object at that path is a file (not a directory), creating the directory cannot proceed and it returns 'file exists'. This happens after the stat succeeded, so the conflict is a real filesystem object, not a race with a missing path.
Source
Thrown at internal/op/fs.go:359
}
case driver.Mkdir:
err = s.MakeDir(ctx, parentDir, dirName)
if err == nil && !utils.IsBool(lazyCache...) {
ClearCache(storage, parentPath)
}
default:
return nil, errs.NotImplement
}
return nil, errors.WithStack(err)
}
return nil, errors.WithMessage(err, "failed to check if dir exists")
}
// dir exists
if f.IsDir() {
return nil, nil
}
// dir to make is a file
return nil, errors.New("file exists")
})
return err
}
func Move(ctx context.Context, storage driver.Driver, srcPath, dstDirPath string, lazyCache ...bool) error {
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
}
srcPath = utils.FixAndCleanPath(srcPath)
dstDirPath = utils.FixAndCleanPath(dstDirPath)
srcRawObj, err := Get(ctx, storage, srcPath)
if err != nil {
return errors.WithMessage(err, "failed to get src object")
}
srcObj := model.UnwrapObj(srcRawObj)
dstDir, err := GetUnwrap(ctx, storage, dstDirPath)
if err != nil {
return errors.WithMessage(err, "failed to get dst dir")View on GitHub (pinned to 843d9dc814)
Solutions
- Delete or rename the existing file that occupies the path, then retry
- Adjust the destination path to avoid the collision (e.g. prefix or different folder name)
- If it came from an upload flow, fix the flow to not create files with the same name as intended directories
Example fix
// before
err := op.MakeDir(ctx, storage, "/data/report.txt/parts")
// after: remove the conflicting file first
if obj, _ := op.GetUnwrap(ctx, storage, "/data/report.txt"); obj != nil && !obj.IsDir() {
_ = op.Remove(ctx, storage, "/data/report.txt")
}
err := op.MakeDir(ctx, storage, "/data/report.txt/parts") Defensive patterns
Strategy: validation
Validate before calling
// Before MakeDir: ensure no file shadows any prefix of the path
p := dstPath
for p != "/" && p != "." {
if obj, err := op.GetUnwrap(ctx, storage, p); err == nil && obj != nil && !obj.IsDir() {
return fmt.Errorf("file %s blocks directory creation", p)
}
p = stdpath.Dir(p)
} Type guard
func pathIsClearOfFiles(ctx context.Context, s driver.Driver, path string) bool {
obj, err := op.GetUnwrap(ctx, s, path)
return err != nil || obj == nil || obj.IsDir()
} Try / catch
if err := op.MakeDir(ctx, storage, dir); err != nil {
if strings.Contains(err.Error(), "file exists") {
// resolve the collision: rename or remove the blocking file
}
} Prevention
- Never upload files whose names collide with planned directory names
- Validate paths in upload pipelines before auto-mkdir
- Use extensions/suffixes for generated files to avoid directory-name collisions
When it happens
Trigger: Calling op.MakeDir on a path whose parent-most conflicting segment is a regular file — e.g. MakeDir('/a/b') where '/a' is a file. Also uploading with auto-mkdir into a path shadowed by an earlier uploaded file of the same name.
Common situations: A previous upload created a file where a directory is now expected (common with generated paths like /books/2024 where 'books' was uploaded as a file); WebDAV clients that mkdir after put; copy/move targets colliding with existing files.
Related errors
- same-name dirs cannot make sub-dir
- error:%s
- directory separator prohibited
- dir name is empty
- cannot move parent dir to child
AI-assisted analysis of AlistGo/alist@843d9dc814 (2026-08-15).
Data as JSON: /api/errors/e4dd745a453ad48d.
Report an issue: GitHub.