{"record":{"id":"3822a3aa2d838a4c","repo":"apache/druid","slug":"root-extensions-directory-s-is-not-a-directory","errorCode":null,"errorMessage":"Root extensions directory [%s] is not a directory!?","messagePattern":"Root extensions directory \\[(.+?)\\] is not a directory!\\?","errorType":"validation","errorClass":"ISE","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java","lineNumber":189,"sourceCode":"    return getFromExtensions(DruidModule.class);\n  }\n\n  /**\n   * Find all the extension files that should be loaded by druid.\n   * <p/>\n   * If user explicitly specifies druid.extensions.loadList, then it will look for those extensions under root\n   * extensions directory. If one of them is not found, druid will fail loudly.\n   * <p/>\n   * If user doesn't specify druid.extension.toLoad (or its value is empty), druid will load all the extensions\n   * under the root extensions directory.\n   *\n   * @return an array of druid extension files that will be loaded by druid process\n   */\n  public void initializeExtensionFilesToLoad()\n  {\n    final File rootExtensionsDir = new File(extensionsConfig.getDirectory());\n    if (rootExtensionsDir.exists() && !rootExtensionsDir.isDirectory()) {\n      throw new ISE(\"Root extensions directory [%s] is not a directory!?\", rootExtensionsDir);\n    }\n    File[] extensionsToLoad;\n    final LinkedHashSet<String> toLoad = extensionsConfig.getLoadList();\n    if (toLoad == null) {\n      extensionsToLoad = rootExtensionsDir.listFiles();\n    } else {\n      final LinkedHashSet<String> validExtensionsToLoad = new LinkedHashSet<>(toLoad);\n      if (validExtensionsToLoad.remove(\"druid-multi-stage-query\")) {\n        log.warn(\n            \"Skipping extension[druid-multi-stage-query] as it is now a core\"\n            + \" capability of Druid. Please remove this extension from your\"\n            + \" configs as it will cause services to fail in future Druid versions.\"\n        );\n      }\n\n      int i = 0;\n      extensionsToLoad = new File[validExtensionsToLoad.size()];\n      for (final String extensionName : validExtensionsToLoad) {","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java#L171-L207","documentation":"ExtensionsLoader.initializeExtensionFilesToLoad() validates the druid.extensions.directory path. This ISE is thrown when the configured root extensions path exists on disk but is a regular file (or other non-directory), so extensions cannot be listed underneath it.","triggerScenarios":"Starting any Druid process with druid.extensions.directory set to a path that exists but is not a directory (e.g. pointing at a jar file or a symlink to a file).","commonSituations":"Misconfigured extensions dir after copying configs between hosts; accidentally pointing druid.extensions.directory at a tarball or single file; a mount point replaced by a file.","solutions":["Check the path with `ls -ld <path>`; it must be a directory","Fix druid.extensions.directory to point to the extensions directory (default: extensions/)","Create the directory if it was intended but missing: `mkdir -p <path>` (a missing path is tolerated; only an existing non-directory fails)","If pointing at a symlink, ensure the symlink resolves to a directory"],"exampleFix":"// before (runtime config)\ndruid.extensions.directory=/opt/druid/extensions.zip\n// after\ndruid.extensions.directory=/opt/druid/extensions","handlingStrategy":"validation","validationCode":"File dir = new File(extensionsDir);\nif (dir.exists() && !dir.isDirectory()) {\n  throw new IllegalStateException(\"druid.extensions.directory must be a directory: \" + dir);\n}","typeGuard":null,"tryCatchPattern":"try { startDruid(); } catch (ISE e) {\n  if (e.getMessage().contains(\"is not a directory\")) { fixExtensionsDirConfig(); }\n  throw e;\n}","preventionTips":["Validate druid.extensions.directory in startup scripts before launching Druid","Never point the setting at archives or individual jars","After host migrations, verify the path resolves to a real directory"],"tags":["extensions","configuration","filesystem"],"backgroundTag":"path-is-not-a-directory","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"}