chinabugotech/hutool · error · IllegalArgumentException

Destination Dir must be a Directory !

Error message

Destination Dir must be a Directory !

What it means

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.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/img/ImgUtil.java:544

	public static void sliceByRowsAndCols(Image srcImage, File destDir, int rows, int cols) {
		sliceByRowsAndCols(srcImage, destDir, IMAGE_TYPE_JPEG, rows, cols);
	}

	/**
	 * 图像切割(指定切片的行数和列数),默认RGB模式
	 *
	 * @param srcImage 源图像,如果非{@link BufferedImage},则默认使用RGB模式
	 * @param destDir  切片目标文件夹
	 * @param format   目标文件格式
	 * @param rows     目标切片行数。默认2,必须是范围 [1, 20] 之内
	 * @param cols     目标切片列数。默认2,必须是范围 [1, 20] 之内
	 * @since 5.8.6
	 */
	public static void sliceByRowsAndCols(Image srcImage, File destDir, String format, int rows, int cols) {
		if (false == destDir.exists()) {
			FileUtil.mkdir(destDir);
		} else if (false == destDir.isDirectory()) {
			throw new IllegalArgumentException("Destination Dir must be a Directory !");
		}

		if (rows <= 0 || rows > 20) {
			rows = 2; // 切片行数
		}
		if (cols <= 0 || cols > 20) {
			cols = 2; // 切片列数
		}
		// 读取源图像
		int srcWidth = srcImage.getWidth(null); // 源图宽度
		int srcHeight = srcImage.getHeight(null); // 源图高度

		int destWidth = NumberUtil.partValue(srcWidth, cols); // 每张切片的宽度
		int destHeight = NumberUtil.partValue(srcHeight, rows); // 每张切片的高度

		// 循环建立切片
		Image tag;
		for (int i = 0; i < rows; i++) {

View on GitHub (pinned to 8870454b2a)

Solutions

  1. Choose a destDir path that is exclusively a directory; delete or rename any conflicting file first.
  2. Check destDir: if it exists and isFile(), remove/rename it before calling slice.
  3. Use a dedicated, freshly created output folder per run.

Example fix

// before
ImgUtil.sliceByRowsAndCols(img, new File("out.png"), "png", 2, 2); // out.png is a file
// after
File dir = new File("out_slices");
if (dir.isFile()) dir.delete();
ImgUtil.sliceByRowsAndCols(img, dir, "png", 2, 2);
Defensive patterns

Strategy: validation

Validate before calling

void requireDirTarget(File d){ if(d.exists() && !d.isDirectory()) throw new IllegalStateException("destDir is a file: "+d); }

Type guard

boolean isUsableDirTarget(File d){ return d==null || !d.exists() || d.isDirectory(); }

Try / catch

try { ImgUtil.sliceByRowsAndCols(img, dir, fmt, r, c); }
catch (IllegalArgumentException e){ if(e.getMessage().contains("must be a Directory")) { dir = new File(dir, "slices"); } else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/e51eda7cb862c4a7. Report an issue: GitHub.