halo-dev/halo · error · ServerWebInputException

Invalid parameter of file

Error message

Invalid parameter of file

What it means

InstallRequest.getFile() throws ServerWebInputException (HTTP 400) 'Invalid parameter of file' when a "file" part exists but is not a FilePart (e.g. it is a FormFieldPart). The installer needs an actual file part to read the JAR bytes, and additionally requires the filename to end in .jar (checked next).

Source

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

    /** Multipart payload for installing a plugin. */
    @Schema(name = "PluginInstallRequest", types = "object")
    public static class InstallRequest {

        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())) {

View on GitHub (pinned to d2f5165f9c)

Solutions

  1. Send the plugin JAR as a real file part (multipart file upload) under the "file" field.
  2. Ensure the field is a binary file upload, not a text form field.
  3. Verify the filename ends in .jar to avoid the follow-on 'Invalid file type' error.

Example fix

// before (file sent as text field)
fd.append('file', '/path/to/plugin.jar')

// after (file sent as binary FilePart)
fd.append('file', fileInput.files[0]) // File object from <input type=file>
Defensive patterns

Strategy: validation

Validate before calling

if (!(multipartData.getFirst("file") instanceof FilePart)) {
    return Mono.error(new ServerWebInputException("Invalid parameter of file"));
}

Type guard

static boolean hasJarFilePart(MultiValueMap<String, Part> fd) {
    Part p = fd.getFirst("file");
    return p instanceof FilePart f
        && f.filename() != null && f.filename().endsWith(".jar");
}

Prevention

When it happens

Trigger: Multipart install request where the "file" field is sent as a plain text form field rather than a file upload; or where a proxy converts the file part into a form field. Also reachable if the part type is unexpected due to a malformed multipart body.

Common situations: Client sends file as a string field by mistake; using the wrong content-type for the part; a tool that flattens file uploads into form fields; test harness posting a form field named file.

Related errors


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