halo-dev/halo · error · ServerWebInputException

Invalid file type, only jar is supported

Error message

Invalid file type, only jar is supported

What it means

Thrown as a ServerWebInputException (HTTP 400) by the plugin install endpoint's InstallRequest.getFile() when the uploaded multipart part named 'file' exists and is a FilePart but its filename does not end with '.jar'. Halo only accepts Java plugin archives, so any other extension (zip, tar, no extension) is rejected before the install pipeline runs.

Source

Thrown at application/src/main/java/run/halo/app/core/endpoint/console/PluginEndpoint.java:662

        private final MultiValueMap<String, Part> multipartData;

        public InstallRequest(MultiValueMap<String, Part> multipartData) {
            this.multipartData = multipartData;
        }

        /** Plugin JAR file. */
        @Schema(requiredMode = NOT_REQUIRED)
        public FilePart getFile() {
            var part = multipartData.getFirst("file");
            if (part == null) {
                throw new ServerWebInputException("Form field file is required");
            }
            if (!(part instanceof FilePart file)) {
                throw new ServerWebInputException("Invalid parameter of file");
            }
            if (!Paths.get(file.filename()).toString().endsWith(".jar")) {
                throw new ServerWebInputException("Invalid file type, only jar is supported");
            }
            return file;
        }

        /** Plugin preset name. Halo finds the plugin from plugin presets. */
        @Schema(requiredMode = NOT_REQUIRED)
        public Mono<String> getPresetName() {
            var part = multipartData.getFirst("presetName");
            if (part == null) {
                return Mono.error(new ServerWebInputException("Form field presetName is required."));
            }
            if (!(part instanceof FormFieldPart presetName)) {
                return Mono.error(new ServerWebInputException("Invalid format of presetName field, string required"));
            }
            if (!StringUtils.hasText(presetName.value())) {
                return Mono.error(new ServerWebInputException("presetName must not be blank"));
            }
            return Mono.just(presetName.value());

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Re-package the plugin as a .jar (run './gradlew build' and grab the jar from build/libs), then upload the artifact whose filename literally ends in lowercase '.jar'.
  2. Check the exact filename your client sends (including hidden extensions and case) and rename it so it ends with '.jar'.
  3. If installing from a preset or URL instead, set the 'source' form field to PRESET or URL and provide presetName/url instead of the file part.

Example fix

// before: client sends plugin.zip as the 'file' part
// after: build and send the jar
//   ./gradlew :build
//   upload build/libs/my-plugin-1.0.0.jar with field name 'file'
Defensive patterns

Strategy: validation

Validate before calling

// before building the install request, check the file's name
String name = selectedFile.getName();
if (!name.toLowerCase(Locale.ROOT).endsWith(".jar")) {
    throw new IllegalArgumentException("Select a .jar plugin archive, got: " + name);
}

Prevention

When it happens

Trigger: POST /apis/api.console.halo.run/v1alpha1/plugins/install with a multipart/form-data body whose 'file' field is a non-.jar file (e.g. plugin.zip, plugin.tar.gz, screenshot.png, or a jar with trailing case differences like .JAR on a case-sensitive path check). Paths.get(file.filename()).toString().endsWith(".jar") is case-sensitive, so '.JAR' or '.Jar' will also fail.

Common situations: User zips the plugin source instead of building the jar; plugin author distributes a .zip that must be unpacked; Windows user with hidden extensions uploads 'plugin.jar.zip'; case mismatch from a renamed file; plugin built but renamed to '.jar.bak' then re-renamed incorrectly.

Related errors


AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14). Data as JSON: /api/errors/4e50a85d3631cd23. Report an issue: GitHub.