{"record":{"id":"e51eda7cb862c4a7","repo":"chinabugotech/hutool","slug":"destination-dir-must-be-a-directory","errorCode":null,"errorMessage":"Destination Dir must be a Directory !","messagePattern":"Destination Dir must be a Directory !","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java","lineNumber":544,"sourceCode":"\tpublic static void sliceByRowsAndCols(Image srcImage, File destDir, int rows, int cols) {\n\t\tsliceByRowsAndCols(srcImage, destDir, IMAGE_TYPE_JPEG, rows, cols);\n\t}\n\n\t/**\n\t * 图像切割（指定切片的行数和列数），默认RGB模式\n\t *\n\t * @param srcImage 源图像，如果非{@link BufferedImage}，则默认使用RGB模式\n\t * @param destDir  切片目标文件夹\n\t * @param format   目标文件格式\n\t * @param rows     目标切片行数。默认2，必须是范围 [1, 20] 之内\n\t * @param cols     目标切片列数。默认2，必须是范围 [1, 20] 之内\n\t * @since 5.8.6\n\t */\n\tpublic static void sliceByRowsAndCols(Image srcImage, File destDir, String format, int rows, int cols) {\n\t\tif (false == destDir.exists()) {\n\t\t\tFileUtil.mkdir(destDir);\n\t\t} else if (false == destDir.isDirectory()) {\n\t\t\tthrow new IllegalArgumentException(\"Destination Dir must be a Directory !\");\n\t\t}\n\n\t\tif (rows <= 0 || rows > 20) {\n\t\t\trows = 2; // 切片行数\n\t\t}\n\t\tif (cols <= 0 || cols > 20) {\n\t\t\tcols = 2; // 切片列数\n\t\t}\n\t\t// 读取源图像\n\t\tint srcWidth = srcImage.getWidth(null); // 源图宽度\n\t\tint srcHeight = srcImage.getHeight(null); // 源图高度\n\n\t\tint destWidth = NumberUtil.partValue(srcWidth, cols); // 每张切片的宽度\n\t\tint destHeight = NumberUtil.partValue(srcHeight, rows); // 每张切片的高度\n\n\t\t// 循环建立切片\n\t\tImage tag;\n\t\tfor (int i = 0; i < rows; i++) {","sourceCodeStart":526,"sourceCodeEnd":562,"githubUrl":"https://github.com/chinabugotech/hutool/blob/8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442/hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java#L526-L562","documentation":"ImgUtil.sliceByRowsAndCols creates destDir if absent, but if a path exists at destDir that is NOT a directory (i.e. a regular file), it throws IllegalArgumentException. The precondition is that destDir must either not exist or be an actual directory.","triggerScenarios":"Passing a File for destDir whose path is already occupied by a regular file; reusing an output path that was previously a file; destDir pointing to a file created by another process.","commonSituations":"Output directory path colliding with an existing file; users passing the image's own path as destDir; CI artifacts left behind from a prior run.","solutions":["Choose a destDir path that is exclusively a directory; delete or rename any conflicting file first.","Check destDir: if it exists and isFile(), remove/rename it before calling slice.","Use a dedicated, freshly created output folder per run."],"exampleFix":"// before\nImgUtil.sliceByRowsAndCols(img, new File(\"out.png\"), \"png\", 2, 2); // out.png is a file\n// after\nFile dir = new File(\"out_slices\");\nif (dir.isFile()) dir.delete();\nImgUtil.sliceByRowsAndCols(img, dir, \"png\", 2, 2);","handlingStrategy":"validation","validationCode":"void requireDirTarget(File d){ if(d.exists() && !d.isDirectory()) throw new IllegalStateException(\"destDir is a file: \"+d); }","typeGuard":"boolean isUsableDirTarget(File d){ return d==null || !d.exists() || d.isDirectory(); }","tryCatchPattern":"try { ImgUtil.sliceByRowsAndCols(img, dir, fmt, r, c); }\ncatch (IllegalArgumentException e){ if(e.getMessage().contains(\"must be a Directory\")) { dir = new File(dir, \"slices\"); } else throw e; }","preventionTips":["Use dedicated output directories per job.","Clear conflicting files before slicing.","Prefer a fresh temp dir for slice output."],"tags":["image","file","argument","io"],"backgroundTag":null,"analyzedSha":"8870454b2a0c29cc6ffd31dcf5667c8ceb2fc442","analyzedAt":"2026-08-14T04:01:12.892Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}