{"record":{"id":"e4dd745a453ad48d","repo":"AlistGo/alist","slug":"file-exists","errorCode":null,"errorMessage":"file exists","messagePattern":"file exists","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/op/fs.go","lineNumber":359,"sourceCode":"\t\t\t\t\t}\n\t\t\t\tcase driver.Mkdir:\n\t\t\t\t\terr = s.MakeDir(ctx, parentDir, dirName)\n\t\t\t\t\tif err == nil && !utils.IsBool(lazyCache...) {\n\t\t\t\t\t\tClearCache(storage, parentPath)\n\t\t\t\t\t}\n\t\t\t\tdefault:\n\t\t\t\t\treturn nil, errs.NotImplement\n\t\t\t\t}\n\t\t\t\treturn nil, errors.WithStack(err)\n\t\t\t}\n\t\t\treturn nil, errors.WithMessage(err, \"failed to check if dir exists\")\n\t\t}\n\t\t// dir exists\n\t\tif f.IsDir() {\n\t\t\treturn nil, nil\n\t\t}\n\t\t// dir to make is a file\n\t\treturn nil, errors.New(\"file exists\")\n\t})\n\treturn err\n}\n\nfunc Move(ctx context.Context, storage driver.Driver, srcPath, dstDirPath string, lazyCache ...bool) error {\n\tif storage.Config().CheckStatus && storage.GetStorage().Status != WORK {\n\t\treturn errors.Errorf(\"storage not init: %s\", storage.GetStorage().Status)\n\t}\n\tsrcPath = utils.FixAndCleanPath(srcPath)\n\tdstDirPath = utils.FixAndCleanPath(dstDirPath)\n\tsrcRawObj, err := Get(ctx, storage, srcPath)\n\tif err != nil {\n\t\treturn errors.WithMessage(err, \"failed to get src object\")\n\t}\n\tsrcObj := model.UnwrapObj(srcRawObj)\n\tdstDir, err := GetUnwrap(ctx, storage, dstDirPath)\n\tif err != nil {\n\t\treturn errors.WithMessage(err, \"failed to get dst dir\")","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/internal/op/fs.go#L341-L377","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nerr := op.MakeDir(ctx, storage, \"/data/report.txt/parts\")\n// after: remove the conflicting file first\nif obj, _ := op.GetUnwrap(ctx, storage, \"/data/report.txt\"); obj != nil && !obj.IsDir() {\n    _ = op.Remove(ctx, storage, \"/data/report.txt\")\n}\nerr := op.MakeDir(ctx, storage, \"/data/report.txt/parts\")","handlingStrategy":"validation","validationCode":"// Before MakeDir: ensure no file shadows any prefix of the path\np := dstPath\nfor p != \"/\" && p != \".\" {\n    if obj, err := op.GetUnwrap(ctx, storage, p); err == nil && obj != nil && !obj.IsDir() {\n        return fmt.Errorf(\"file %s blocks directory creation\", p)\n    }\n    p = stdpath.Dir(p)\n}","typeGuard":"func pathIsClearOfFiles(ctx context.Context, s driver.Driver, path string) bool {\n    obj, err := op.GetUnwrap(ctx, s, path)\n    return err != nil || obj == nil || obj.IsDir()\n}","tryCatchPattern":"if err := op.MakeDir(ctx, storage, dir); err != nil {\n    if strings.Contains(err.Error(), \"file exists\") {\n        // resolve the collision: rename or remove the blocking file\n    }\n}","preventionTips":["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"],"tags":["filesystem","mkdir","path-conflict"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}