testcontainers/testcontainers-java · error · ContainerLaunchException

Extension ' ' could not be mounted. It is not a directory.

Error message

Extension '{path}' could not be mounted. It is not a directory.

What it means

After checking existence, the MountableFile-based withExtension validates that the resolved path is a directory, because HiveMQ extensions are mounted as folders under /opt/hivemq/temp-extensions/. Mounting a plain file would produce a broken extension, so the library throws this ContainerLaunchException.

Solutions

  1. Pass the extension directory (the folder containing hivemq-extension.xml), not a file inside it.
  2. Unpack any zipped extension to a directory first, then wrap the directory with MountableFile.forHostPath(dir).
  3. Check the resolved path with File.isDirectory() in a debugger/print to confirm what you are passing.

Example fix

// before
withExtension(MountableFile.forHostPath("ext/my-extension.zip")); // a file

// after
File dir = unzipTo(new File("ext/my-extension.zip"), tempDir);
withExtension(MountableFile.forHostPath(dir)); // directory containing hivemq-extension.xml
Defensive patterns

Strategy: validation

Validate before calling

File dir = new File(mountableFile.getResolvedPath());
if (!dir.isDirectory()) {
    throw new IllegalArgumentException("Expected an extension directory, got: " + dir);
}

Prevention

When it happens

Trigger: Passing a MountableFile that resolves to a regular file (e.g. a .zip or a single hivemq-extension.xml) instead of the extension's directory.

Common situations: Pointing at an archive or a single descriptor file instead of the unpacked extension folder; a symlink that resolves to a file; mixing up the extension jar path with the extension directory.

Related errors


AI-assisted analysis of testcontainers/testcontainers-java@8e549514e3 (2026-09-12). Data as JSON: /api/errors/737652b0757613fe. Report an issue: GitHub.

Appendix: source

Thrown at modules/hivemq/src/main/java/org/testcontainers/hivemq/HiveMQContainer.java:251

     * It must at least contain a valid hivemq-extension.xml and a valid extension.jar in order to be executed.
     * The directory-name is taken from the id defined in the hivemq-extension.xml.
     * <p>
     * Must be called before the container is started.
     * <p>
     * The contents of the '/opt/hivemq/temp-extensions/' directory are copied to '/opt/hivemq/extensions/' before the container is started.
     *
     * @param mountableExtension the extension folder on the host machine
     * @return self
     */
    public @NotNull HiveMQContainer withExtension(final @NotNull MountableFile mountableExtension) {
        final File extensionDir = new File(mountableExtension.getResolvedPath());
        if (!extensionDir.exists()) {
            throw new ContainerLaunchException(
                "Extension '" + mountableExtension.getFilesystemPath() + "' could not be mounted. It does not exist."
            );
        }
        if (!extensionDir.isDirectory()) {
            throw new ContainerLaunchException(
                "Extension '" +
                mountableExtension.getFilesystemPath() +
                "' could not be mounted. It is not a directory."
            );
        }
        try {
            final String extensionDirName = getExtensionDirectoryName(extensionDir);
            final String containerPath = "/opt/hivemq/temp-extensions/" + extensionDirName;
            withCopyFileToContainer(cloneWithFileMode(mountableExtension), containerPath);
            LOGGER.info("Putting extension '{}' into '{}'", extensionDirName, containerPath);
        } catch (final Exception e) {
            throw new ContainerLaunchException(e.getMessage() == null ? "" : e.getMessage(), e);
        }
        return self();
    }

    private @NotNull String getExtensionDirectoryName(final @NotNull File extensionDirectory) throws IOException {
        final File file = new File(extensionDirectory, "hivemq-extension.xml");

View on GitHub (pinned to 8e549514e3)