{"record":{"id":"801fcdb7b0e42b68","repo":"halo-dev/halo","slug":"invalid-parameter-of-file-binary-data-is-required","errorCode":null,"errorMessage":"Invalid parameter of file, binary data is required","messagePattern":"Invalid parameter of file, binary data is required","errorType":"http","errorClass":"ServerWebInputException","httpStatus":400,"severity":"error","filePath":"application/src/main/java/run/halo/app/theme/endpoint/ThemeEndpoint.java","lineNumber":528,"sourceCode":"    }\n\n    /** Multipart payload for installing a theme. */\n    @Schema(name = \"ThemeInstallRequest\", types = \"object\")\n    public static class InstallRequest {\n\n        @Schema(hidden = true)\n        private final MultiValueMap<String, Part> multipartData;\n\n        public InstallRequest(MultiValueMap<String, Part> multipartData) {\n            this.multipartData = multipartData;\n        }\n\n        /** Theme zip file. */\n        @Schema(requiredMode = REQUIRED)\n        FilePart getFile() {\n            Part part = multipartData.getFirst(\"file\");\n            if (!(part instanceof FilePart file)) {\n                throw new ServerWebInputException(\"Invalid parameter of file, binary data is required\");\n            }\n            if (!Paths.get(file.filename()).toString().endsWith(\".zip\")) {\n                throw new ServerWebInputException(\"Invalid file type, only zip format is supported\");\n            }\n            return file;\n        }\n    }\n\n    /**\n     * Payload for installing a theme from a remote URI.\n     *\n     * @param uri remote URI of the theme ZIP file\n     */\n    public record InstallFromUriRequest(\n            @Schema(requiredMode = REQUIRED) URI uri) {}\n\n    Mono<ServerResponse> install(ServerRequest request) {\n        return request.multipartData()","sourceCodeStart":510,"sourceCodeEnd":546,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/theme/endpoint/ThemeEndpoint.java#L510-L546","documentation":"InstallRequest.getFile() reads the multipart part named 'file' from the install request. If that part exists but is not a FilePart (no filename / not binary), a ServerWebInputException (HTTP 400) 'Invalid parameter of file, binary data is required' is thrown. This is the install counterpart of the upgrade file-type guard, checked before the .zip extension.","triggerScenarios":"POST to the theme install endpoint with a multipart 'file' part sent as a plain text form field rather than a binary file part. Reached via the install handler -> InstallRequest::getFile.","commonSituations":"Wrong curl/Postman usage (-F file=value instead of -F file=@path); frontend appending a non-File value to FormData; malformed Content-Disposition missing the filename parameter.","solutions":["Send a real binary file part: curl -F 'file=@theme.zip'.","On the frontend, append a File object: formData.append('file', fileInput.files[0]).","Ensure the part's Content-Disposition includes a filename.","Do not manually set Content-Type: multipart/form-data; let the browser set the boundary."],"exampleFix":"// before (frontend, wrong): sending a string\n//   formData.append('file', 'some-value')\n// after: append the actual File\n//   formData.append('file', fileInput.files[0], 'theme.zip')","handlingStrategy":"validation","validationCode":"// Client-side: ensure binary File is attached for install\nconst f = fileInput.files && fileInput.files[0];\nif (!(f instanceof File)) {\n    showError(\"Binary file data is required.\");\n    return;\n}\nconst fd = new FormData();\nfd.append(\"file\", f);","typeGuard":"function isBinaryFilePart(v) { return v instanceof File; }","tryCatchPattern":"try { await installTheme(fd); }\ncatch (e) { if (/binary data is required/.test(e.message)) alert(\"Attach a file, not text.\"); throw e; }","preventionTips":["Append a File object to FormData under the 'file' key, never a string.","Let the browser set the multipart Content-Type/boundary.","In curl use -F 'file=@theme.zip', not -F file=value.","Verify the part's Content-Disposition includes a filename."],"tags":["theme","multipart","upload","api","validation"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}