halo-dev/halo · error · ServerWebInputException
Invalid file type, only zip format is supported
Error message
Invalid file type, only zip format is supported
What it means
After confirming the 'file' part is a FilePart, InstallRequest.getFile() resolves the filename to a Path string and checks it ends with '.zip'. If not, a ServerWebInputException (HTTP 400) 'Invalid file type, only zip format is supported' is thrown. Only ZIP archives may be installed.
Source
Thrown at application/src/main/java/run/halo/app/theme/endpoint/ThemeEndpoint.java:531
@Schema(name = "ThemeInstallRequest", types = "object")
public static class InstallRequest {
@Schema(hidden = true)
private final MultiValueMap<String, Part> multipartData;
public InstallRequest(MultiValueMap<String, Part> multipartData) {
this.multipartData = multipartData;
}
/** Theme zip file. */
@Schema(requiredMode = REQUIRED)
FilePart getFile() {
Part part = multipartData.getFirst("file");
if (!(part instanceof FilePart file)) {
throw new ServerWebInputException("Invalid parameter of file, binary data is required");
}
if (!Paths.get(file.filename()).toString().endsWith(".zip")) {
throw new ServerWebInputException("Invalid file type, only zip format is supported");
}
return file;
}
}
/**
* Payload for installing a theme from a remote URI.
*
* @param uri remote URI of the theme ZIP file
*/
public record InstallFromUriRequest(
@Schema(requiredMode = REQUIRED) URI uri) {}
Mono<ServerResponse> install(ServerRequest request) {
return request.multipartData()
.map(InstallRequest::new)
.map(InstallRequest::getFile)
.flatMap(filePart -> themeService.install(filePart.content()))View on GitHub (pinned to d2f5165f9c)
Solutions
- Repackage the theme as a .zip and re-upload.
- Confirm the uploaded filename ends in '.zip' (note the check is on the filename, so double extensions like .zip.txt will fail).
- If your theme source is a tarball, convert it to zip before install.
Example fix
# before # tar -czf theme.tar.gz theme/ # after # zip -r theme.zip theme/
Defensive patterns
Strategy: validation
Validate before calling
// Client-side: enforce .zip before install
const name = Paths.get(file.name) /* conceptual */;
if (!file.name.toLowerCase().endsWith(".zip")) {
showError("Only zip format is supported.");
return;
} Type guard
function isZipArchive(name) {
return String(name).toLowerCase().endsWith(".zip");
} Try / catch
try { await installTheme(fd); }
catch (e) { if (/only zip format/.test(e.message)) alert("Use a .zip archive."); throw e; } Prevention
- Distribute and upload themes only as .zip archives.
- Validate the filename extension client-side before upload.
- Avoid double extensions that break the suffix check.
- Verify with `unzip -t theme.zip` locally before uploading.
When it happens
Trigger: Installing a theme packaged as a non-zip archive (.tar.gz, .rar, .7z) or a renamed file whose effective path does not end in .zip. Uses Paths.get(filename).toString().endsWith(".zip") so it normalizes path separators first.
Common situations: Downloading a theme distributed as tar.gz; build tooling emitting the wrong archive format; OS hiding/altering extensions.
Related errors
- Invalid multipart type of file
- Only zip extension supported
- Invalid parameter of file, binary data is required
- Invalid part of file
- Invalid part of policyName
AI-assisted analysis of halo-dev/halo@d2f5165f9c (2026-08-14).
Data as JSON: /api/errors/a71ea7e96f6a6902.
Report an issue: GitHub.