{"record":{"id":"6093c5183579163e","repo":"apache/druid","slug":"path-s-is-not-writable-check-permissions","errorCode":null,"errorMessage":"Path [%s] is not writable, check permissions","messagePattern":"Path \\[(.+?)\\] is not writable, check permissions","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java","lineNumber":490,"sourceCode":"  }\n\n  @SuppressForbidden(reason = \"Files#createTempDirectory\")\n  public static File createTempDirInLocation(final Path parentDirectory, @Nullable final String prefix)\n  {\n    try {\n      final Path tmpPath = Files.createTempDirectory(\n          parentDirectory,\n          prefix == null || prefix.isEmpty() ? \"druid\" : prefix\n      );\n      return tmpPath.toFile();\n    }\n    catch (IOException e) {\n      // Some inspection to improve error messages.\n      if (e instanceof NoSuchFileException && !parentDirectory.toFile().exists()) {\n        throw new ISE(\"Path [%s] does not exist\", parentDirectory);\n      } else if ((e instanceof FileSystemException && e.getMessage().contains(\"Read-only file system\"))\n                 || (e instanceof AccessDeniedException)) {\n        throw new ISE(\"Path [%s] is not writable, check permissions\", parentDirectory);\n      } else {\n        // Well, maybe it was something else.\n        throw new ISE(e, \"Failed to create temporary directory in path [%s]\", parentDirectory);\n      }\n    }\n  }\n\n  /**\n   * Create \"directory\" and all intermediate directories as needed. If the directory is successfully created, or already\n   * exists, returns quietly. Otherwise, throws an IOException.\n   *\n   * Simpler to use than {@link File#mkdirs()}, and more reliable since it is safe from races where two threads try\n   * to create the same directory at the same time.\n   *\n   * The name is inspired by UNIX {@code mkdir -p}, which has the same behavior.\n   */\n  @SuppressForbidden(reason = \"File#mkdirs\")\n  public static void mkdirp(final File directory) throws IOException","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/common/FileUtils.java#L472-L508","documentation":"FileUtils.createTempDirInLocation throws this ISE when the JVM cannot create a temporary directory because the OS reported the parent path is not writable. It maps AccessDeniedException or a 'Read-only file system' FileSystemException from the underlying createDirectory call to this clearer message. It indicates a filesystem permission or mount-state problem, not a bug in caller code.","triggerScenarios":"Calling FileUtils.createTempDir (which delegates to createTempDirInLocation) with a parent directory the process cannot write to, on a read-only mounted filesystem, or where the directory's permission bits deny write access to the running user.","commonSituations":"Configuring druid.server.tempDir or intermediate persist dirs on a read-only container filesystem; running Druid as a non-root user without write access to java.io.tmpdir; disk remounted read-only after hardware errors; Kubernetes readOnlyRootFilesystem without an emptyDir mount.","solutions":["Check and fix permissions on the parent directory: chown/chmod so the process user has write access","Point the temp-dir configuration at a writable location (e.g. a writable volume or /tmp)","If the filesystem was remounted read-only, remount it read-write or fix the underlying disk issue","In containers, mount a writable emptyDir/PV for temp directories and avoid readOnlyRootFilesystem without mounts","Verify with: sudo -u <druid-user> touch <path>/writetest"],"exampleFix":"// before\nFileUtils.createTempDir(new File(\"/opt/druid/tmp\")); // /opt is read-only\n// after\nFileUtils.createTempDir(new File(\"/var/tmp/druid\")); // writable volume","handlingStrategy":"try-catch","validationCode":"File dir = new File(path);\nif (!dir.isDirectory()) throw new IllegalStateException(\"Not a directory: \" + path);\nFile probe = new File(dir, \".write-probe\");\ntry { if (!probe.createNewFile()) throw new IllegalStateException(\"Not writable\"); }\nfinally { probe.delete(); }","typeGuard":"static boolean isWritableDir(File dir) {\n  return dir != null && dir.isDirectory() && dir.canWrite();\n}","tryCatchPattern":"try {\n  File tmp = FileUtils.createTempDir(parent);\n} catch (ISE e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"not writable\")) {\n    // fix permissions or switch to fallback dir\n    tmp = FileUtils.createTempDir(new File(System.getProperty(\"java.io.tmpdir\")));\n  } else throw e;\n}","preventionTips":["Run the process as a user with write access to configured temp paths","Mount a writable volume for temp dirs in containers with read-only root filesystems","Add a startup health check that probes write access to all configured directories","Monitor for filesystems remounting read-only (dmesg / mount state alerts)"],"tags":["filesystem","permissions","io"],"backgroundTag":"permission-denied","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}