HMCL-dev/HMCL · error · IllegalArgumentException

The extension of is not 'sh', 'bash', 'ps1' or 'command'…

Error message

The extension of  is not 'sh', 'bash', 'ps1' or 'command' in macOS/Linux

What it means

DefaultLauncher.makeLaunchScript requires that on macOS/Linux the script file extension be sh, bash, command, or ps1 (ps1 selects PowerShell output). It throws IllegalArgumentException("The extension of <file> is not 'sh', 'bash', 'ps1' or 'command' in macOS/Linux") when the target file has another extension on a non-Windows host.

Solutions

  1. Use a .sh (or .bash/.command/.ps1) file name when exporting on macOS/Linux.
  2. Rename the script file extension to .sh before calling makeLaunchScript.
  3. Branch on the OS in your code to choose the correct extension, as the launcher itself does with isWindows.
  4. Remember to chmod +x the generated .sh script afterwards to make it executable.

Example fix

// before
// launcher.makeLaunchScript(Path.of("game.bat"), ...); // on Linux
// after
// launcher.makeLaunchScript(Path.of("game.sh"), ...); // on Linux
Defensive patterns

Strategy: validation

Validate before calling

String ext = FileUtils.getExtension(scriptFile);
boolean isWindows = OS.WINDOWS == OperatingSystem.CURRENT_OS;
if (!isWindows && !"ps1".equals(ext) && !("sh".equalsIgnoreCase(ext) || "bash".equalsIgnoreCase(ext) || "command".equalsIgnoreCase(ext))) {
    throw new IllegalArgumentException("Use .sh/.bash/.command/.ps1 on macOS/Linux, got: " + ext);
}

Try / catch

try {
    launcher.makeLaunchScript(scriptFile, ...);
} catch (IllegalArgumentException e) {
    // rename the script file to .sh (or .ps1) and retry
}

Prevention

When it happens

Trigger: Calling makeLaunchScript(scriptFile, ...) on Linux/macOS with a file whose extension is not one of sh/bash/command/ps1 — e.g. exporting game.bat or game.txt on a Linux machine.

Common situations: Copy-pasting a Windows-oriented export path (.bat) on Linux; text editors appending .txt; CI scripts generating scripts with a fixed .bat name regardless of OS.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of HMCL-dev/HMCL@24702dc5a0 (2026-09-10). Data as JSON: /api/errors/87f7338079b22718. Report an issue: GitHub.

Appendix: source

Thrown at HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java:873

            classpath.add(FileUtils.getAbsolutePath(selectedOptiFineInstallerFile));
        }
        return classpath;
    }

    @Override
    public void makeLaunchScript(Path scriptFile) throws IOException {
        boolean isWindows = OperatingSystem.WINDOWS == OperatingSystem.CURRENT_OS;

        Path nativeFolder = getNativeFolder();

        String scriptExtension = FileUtils.getExtension(scriptFile);
        boolean usePowerShell = "ps1".equals(scriptExtension);

        if (!usePowerShell) {
            if (isWindows && !scriptExtension.equalsIgnoreCase("bat"))
                throw new IllegalArgumentException("The extension of " + scriptFile + " is not 'bat' or 'ps1' in Windows");
            else if (!isWindows && !(scriptExtension.equalsIgnoreCase("sh") || scriptExtension.equalsIgnoreCase("command") || scriptExtension.equalsIgnoreCase("bash")))
                throw new IllegalArgumentException("The extension of " + scriptFile + " is not 'sh', 'bash', 'ps1' or 'command' in macOS/Linux");
        }

        final Command commandLine = generateCommandLine(nativeFolder);
        final String command = usePowerShell ? null : commandLine.commandLine.toString();
        Map<String, String> envVars = getEnvVars(nativeFolder);

        if (isWindows && !usePowerShell) {
            // https://stackoverflow.com/a/28452546
            // https://learn.microsoft.com/troubleshoot/windows-client/shell-experience/command-line-string-limitation
            if (command.length() > 32767) {
                throw new CommandTooLongException();
            }
        }

        if (isUsingLog4j())
            extractLog4jConfigurationFile();

        if (!options.isUseCustomNatives())

View on GitHub (pinned to 24702dc5a0)