apache/druid · error · ISE

Root extensions directory [%s] is not a directory!?

Error message

Root extensions directory [%s] is not a directory!?

What it means

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.

Source

Thrown at processing/src/main/java/org/apache/druid/guice/ExtensionsLoader.java:189

    return getFromExtensions(DruidModule.class);
  }

  /**
   * Find all the extension files that should be loaded by druid.
   * <p/>
   * If user explicitly specifies druid.extensions.loadList, then it will look for those extensions under root
   * extensions directory. If one of them is not found, druid will fail loudly.
   * <p/>
   * If user doesn't specify druid.extension.toLoad (or its value is empty), druid will load all the extensions
   * under the root extensions directory.
   *
   * @return an array of druid extension files that will be loaded by druid process
   */
  public void initializeExtensionFilesToLoad()
  {
    final File rootExtensionsDir = new File(extensionsConfig.getDirectory());
    if (rootExtensionsDir.exists() && !rootExtensionsDir.isDirectory()) {
      throw new ISE("Root extensions directory [%s] is not a directory!?", rootExtensionsDir);
    }
    File[] extensionsToLoad;
    final LinkedHashSet<String> toLoad = extensionsConfig.getLoadList();
    if (toLoad == null) {
      extensionsToLoad = rootExtensionsDir.listFiles();
    } else {
      final LinkedHashSet<String> validExtensionsToLoad = new LinkedHashSet<>(toLoad);
      if (validExtensionsToLoad.remove("druid-multi-stage-query")) {
        log.warn(
            "Skipping extension[druid-multi-stage-query] as it is now a core"
            + " capability of Druid. Please remove this extension from your"
            + " configs as it will cause services to fail in future Druid versions."
        );
      }

      int i = 0;
      extensionsToLoad = new File[validExtensionsToLoad.size()];
      for (final String extensionName : validExtensionsToLoad) {

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Check the path with `ls -ld <path>`; it must be a directory
  2. Fix druid.extensions.directory to point to the extensions directory (default: extensions/)
  3. Create the directory if it was intended but missing: `mkdir -p <path>` (a missing path is tolerated; only an existing non-directory fails)
  4. If pointing at a symlink, ensure the symlink resolves to a directory

Example fix

// before (runtime config)
druid.extensions.directory=/opt/druid/extensions.zip
// after
druid.extensions.directory=/opt/druid/extensions
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(extensionsDir);
if (dir.exists() && !dir.isDirectory()) {
  throw new IllegalStateException("druid.extensions.directory must be a directory: " + dir);
}

Try / catch

try { startDruid(); } catch (ISE e) {
  if (e.getMessage().contains("is not a directory")) { fixExtensionsDirConfig(); }
  throw e;
}

Prevention

When it happens

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

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

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/3822a3aa2d838a4c. Report an issue: GitHub.