{"record":{"id":"d0a4ba09b428c6ce","repo":"HMCL-dev/HMCL","slug":"the-extension-of-is-not-bat-or-ps1-in-windows","errorCode":null,"errorMessage":"The extension of  is not 'bat' or 'ps1' in Windows","messagePattern":"The extension of  is not 'bat' or 'ps1' in Windows","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java","lineNumber":871,"sourceCode":"                // With ModLauncher, OptiFine is discovered via HMCLTransformerDiscoveryService, not classpath.\n                !GameComponentAnalyzer.MOD_LAUNCHER_MAIN.equals(manifest.mainClass())) {\n            classpath.add(FileUtils.getAbsolutePath(selectedOptiFineInstallerFile));\n        }\n        return classpath;\n    }\n\n    @Override\n    public void makeLaunchScript(Path scriptFile) throws IOException {\n        boolean isWindows = OperatingSystem.WINDOWS == OperatingSystem.CURRENT_OS;\n\n        Path nativeFolder = getNativeFolder();\n\n        String scriptExtension = FileUtils.getExtension(scriptFile);\n        boolean usePowerShell = \"ps1\".equals(scriptExtension);\n\n        if (!usePowerShell) {\n            if (isWindows && !scriptExtension.equalsIgnoreCase(\"bat\"))\n                throw new IllegalArgumentException(\"The extension of \" + scriptFile + \" is not 'bat' or 'ps1' in Windows\");\n            else if (!isWindows && !(scriptExtension.equalsIgnoreCase(\"sh\") || scriptExtension.equalsIgnoreCase(\"command\") || scriptExtension.equalsIgnoreCase(\"bash\")))\n                throw new IllegalArgumentException(\"The extension of \" + scriptFile + \" is not 'sh', 'bash', 'ps1' or 'command' in macOS/Linux\");\n        }\n\n        final Command commandLine = generateCommandLine(nativeFolder);\n        final String command = usePowerShell ? null : commandLine.commandLine.toString();\n        Map<String, String> envVars = getEnvVars(nativeFolder);\n\n        if (isWindows && !usePowerShell) {\n            // https://stackoverflow.com/a/28452546\n            // https://learn.microsoft.com/troubleshoot/windows-client/shell-experience/command-line-string-limitation\n            if (command.length() > 32767) {\n                throw new CommandTooLongException();\n            }\n        }\n\n        if (isUsingLog4j())\n            extractLog4jConfigurationFile();","sourceCodeStart":853,"sourceCodeEnd":889,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCLCore/src/main/java/org/jackhuang/hmcl/launch/DefaultLauncher.java#L853-L889","documentation":"DefaultLauncher.makeLaunchScript writes a launch script and requires, on Windows, a .bat extension (unless PowerShell .ps1 was selected). It throws IllegalArgumentException(\"The extension of <file> is not 'bat' or 'ps1' in Windows\") when the script file path on a Windows host has any other extension, because the generated script format would not be runnable.","triggerScenarios":"Calling makeLaunchScript(scriptFile, ...) on Windows with a file whose extension is not bat/ps1 — e.g. saving a launch script as .sh or .txt while running on Windows.","commonSituations":"Users exporting a script to share with Linux friends while on Windows; saving with a .txt extension added by a text editor; automation passing a fixed filename without checking OS.","solutions":["Use a .bat file name when exporting the launch script on Windows (or .ps1 for PowerShell).","Rename the target script file's extension to .bat before calling makeLaunchScript.","On a Windows machine that needs a shell script, export .ps1 instead of .sh.","Pick the export format according to the current OS rather than a fixed path."],"exampleFix":"// before\n// launcher.makeLaunchScript(Path.of(\"game.sh\"), ...); // on Windows\n// after\n// launcher.makeLaunchScript(Path.of(\"game.bat\"), ...); // on Windows","handlingStrategy":"validation","validationCode":"String ext = FileUtils.getExtension(scriptFile);\nboolean isWindows = OS.WINDOWS == OperatingSystem.CURRENT_OS;\nif (isWindows && !\"ps1\".equals(ext) && !\"bat\".equalsIgnoreCase(ext)) {\n    throw new IllegalArgumentException(\"Use .bat or .ps1 on Windows, got: \" + ext);\n}","typeGuard":null,"tryCatchPattern":"try {\n    launcher.makeLaunchScript(scriptFile, ...);\n} catch (IllegalArgumentException e) {\n    // rename the script file to .bat or .ps1 and retry\n}","preventionTips":["Choose the script extension based on the current OS","Never hardcode .sh paths in Windows export flows","Strip accidental .txt suffixes added by editors"],"tags":["launcher","windows","script","file-extension"],"backgroundTag":"invalid-argument-value","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}