dianping/cat · error · IOException

Can't write to an existing directory(%s)

Error message

Can't write to an existing directory(%s)

What it means

Thrown by Files.writeTo(File, byte[]) when the target File object is an existing directory. The utility refuses to open a FileOutputStream on a directory because the OS would reject it anyway; failing fast with a clear message is preferable. It is a plain IOException, so it propagates to whatever file-persistence logic called it.

Source

Thrown at cat-client/src/main/java/com/dianping/cat/support/Files.java:246

      }

      public String readFrom(InputStream is, String charsetName) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream(16 * 1024);

         copy(is, baos, AutoClose.INPUT);
         return baos.toString(charsetName);
      }

      public String readUtf8String(InputStream is) throws IOException {
         ByteArrayOutputStream baos = new ByteArrayOutputStream(16 * 1024);

         copy(is, baos, AutoClose.INPUT);
         return baos.toString("utf-8");
      }

      public void writeTo(File file, byte[] data) throws IOException {
         if (file.isDirectory()) {
            throw new IOException(String.format("Can't write to an existing directory(%s)", file));
         }

         Dir.INSTANCE.createDir(file.getParentFile());

         FileOutputStream fos = new FileOutputStream(file);

         try {
            fos.write(data);
         } finally {
            try {
               fos.close();
            } catch (IOException e) {
               // ignore it
            }
         }
      }

      public void writeTo(File file, String data) throws IOException {

View on GitHub (pinned to e815e74d4c)

Solutions

  1. Log or inspect the File object right before the call: print getAbsolutePath() and isDirectory() to find why it resolves to a folder.
  2. Fix the path construction so it always appends a concrete file name (and extension) after the parent directory.
  3. If the file name is dynamic, guard it: reject empty/blank names before calling writeTo.
  4. As a defensive measure for races, check isDirectory() first and either delete the stray directory or pick an alternate path.

Example fix

// before
File f = new File(baseDir + domain); // domain dir, no file name
Files.INSTANCE.writeTo(f, bytes); // throws

// after
File dir = new File(baseDir, domain);
File f = new File(dir, domain + ".ser");
Files.INSTANCE.writeTo(f, bytes);
Defensive patterns

Strategy: validation

Validate before calling

if (file == null || file.isDirectory()) {
    throw new IllegalArgumentException("Not a writable file path: " + file);
}

Try / catch

catch (IOException e) { /* message names the directory; fix path and retry once manually */ }

Prevention

When it happens

Trigger: Calling Files.INSTANCE.writeTo(file, data) (or the convenience writeUtf8StringTo/writeCharsTo wrappers) where file.isDirectory() is true — e.g. the path points at an existing folder, or a path string was built without a file name component ("/data/cat" instead of "/data/cat/report.txt").

Common situations: Misbuilt output paths (directory prefix passed instead of full file path), a file name that is empty so getPath() resolves to the parent directory, or a race where a directory was created at the location a file was expected. Common in report/storage writers that derive file paths from domain/date concatenation.

Related errors


AI-assisted analysis of dianping/cat@e815e74d4c (2026-08-14). Data as JSON: /api/errors/401557bc496d873d. Report an issue: GitHub.