{"record":{"id":"59000f0d12d85747","repo":"SonarSource/sonarqube","slug":"s-is-not-a-directory","errorCode":null,"errorMessage":"'%s' is not a directory","messagePattern":"'(.+?)' is not a directory","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"server/sonar-process/src/main/java/org/sonar/process/FileUtils2.java","lineNumber":142,"sourceCode":"  /**\n   * Size of file or directory, in bytes. In case of a directory,\n   * the size is the sum of the sizes of all files recursively traversed.\n   *\n   * This implementation is recommended over commons-io\n   * {@code FileUtils#sizeOf(File)} which suffers from slow usage of Java IO.\n   *\n   * @throws IOException if files can't be traversed or size attribute is not present\n   * @see BasicFileAttributes#size()\n   */\n  public static long sizeOf(Path path) throws IOException {\n    SizeVisitor visitor = new SizeVisitor();\n    Files.walkFileTree(path, visitor);\n    return visitor.size;\n  }\n\n  private static void cleanDirectoryImpl(Path path) throws IOException {\n    if (!path.toFile().isDirectory()) {\n      throw new IllegalArgumentException(format(\"'%s' is not a directory\", path));\n    }\n    Files.walkFileTree(path, FOLLOW_LINKS, CleanDirectoryFileVisitor.VISIT_MAX_DEPTH, new CleanDirectoryFileVisitor(path));\n  }\n\n  private static void deleteDirectoryImpl(Path path) throws IOException {\n    Files.walkFileTree(path, DeleteRecursivelyFileVisitor.INSTANCE);\n  }\n\n  /**\n   * This visitor is intended to be used to visit direct children of directory <strong>or a symLink to a directory</strong>,\n   * so, with a max depth of {@link #VISIT_MAX_DEPTH 1}. Each direct children will either be directly deleted (if file)\n   * or recursively deleted (if directory).\n   */\n  private static class CleanDirectoryFileVisitor extends SimpleFileVisitor<Path> {\n    public static final int VISIT_MAX_DEPTH = 1;\n\n    private final Path path;\n    private final boolean symLink;","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/SonarSource/sonarqube/blob/184c821202192afc1c599fc912d0889b69fffa53/server/sonar-process/src/main/java/org/sonar/process/FileUtils2.java#L124-L160","documentation":"cleanDirectoryImpl throws IllegalArgumentException when the path passed to cleanDirectory is not a directory. Cleaning only makes sense on directories, so the precondition is enforced before walking the tree.","triggerScenarios":"Calling FileUtils2.cleanDirectory(path) where path does not exist or is a regular file.","commonSituations":"Wrong path in configuration; directory deleted before cleaning; using a file path (e.g. a data file) instead of its parent directory.","solutions":["Ensure the path exists and is a directory before calling cleanDirectory (path.toFile().isDirectory())","Fix the configured path value","Create the directory first if it should exist"],"exampleFix":"// before\nFileUtils2.cleanDirectory(dir);\n// after\nFile d = new File(dir);\nif (!d.isDirectory()) {\n  throw new IllegalArgumentException(dir + \" is not a directory\");\n}\nFileUtils2.cleanDirectory(dir);","handlingStrategy":"validation","validationCode":"File d = new File(path);\nif (!d.exists() || !d.isDirectory()) { throw new IllegalArgumentException(path + \" must be an existing directory\"); }\nFileUtils2.cleanDirectory(path);","typeGuard":null,"tryCatchPattern":"try { FileUtils2.cleanDirectory(path); } catch (IllegalArgumentException e) { /* create the dir or fix the path */ }","preventionTips":["Validate existence and directory type before cleaning","Create missing directories with Files.createDirectories() first","Centralize path resolution so file-vs-directory mistakes surface early"],"tags":["filesystem","io","directory"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"184c821202192afc1c599fc912d0889b69fffa53","analyzedAt":"2026-09-09T12:23:51.573Z","contentChangedAt":"2026-09-09T12:23:51.573Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}