{"record":{"id":"db269857529fe156","repo":"halo-dev/halo","slug":"invalid-part-of-file","errorCode":null,"errorMessage":"Invalid part of file","messagePattern":"Invalid part of file","errorType":"http","errorClass":"ServerWebInputException","httpStatus":400,"severity":"warning","filePath":"application/src/main/java/run/halo/app/core/attachment/endpoint/AttachmentEndpoint.java","lineNumber":169,"sourceCode":"        /** Attachment file. */\n        @Schema(requiredMode = REQUIRED)\n        FilePart getFile();\n\n        /** Storage policy {@code metadata.name}. */\n        @Schema(requiredMode = REQUIRED)\n        String getPolicyName();\n\n        /** Attachment group {@code metadata.name}. */\n        String getGroupName();\n    }\n\n    public record UploadRequest(MultiValueMap<String, Part> formData) implements IUploadRequest {\n\n        public FilePart getFile() {\n            if (formData.getFirst(\"file\") instanceof FilePart file) {\n                return file;\n            }\n            throw new ServerWebInputException(\"Invalid part of file\");\n        }\n\n        public String getPolicyName() {\n            if (formData.getFirst(\"policyName\") instanceof FormFieldPart form) {\n                return form.value();\n            }\n            throw new ServerWebInputException(\"Invalid part of policyName\");\n        }\n\n        @Override\n        public String getGroupName() {\n            if (formData.getFirst(\"groupName\") instanceof FormFieldPart form) {\n                return form.value();\n            }\n            return null;\n        }\n    }\n}","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/core/attachment/endpoint/AttachmentEndpoint.java#L151-L187","documentation":"UploadRequest is the multipart upload payload. getFile() throws ServerWebInputException (HTTP 400) 'Invalid part of file' when the multipart form either has no \"file\" part at all or the part is not a FilePart (e.g. it is a plain FormFieldPart). Halo needs an actual file part to stream into attachment storage.","triggerScenarios":"Multipart POST to the attachment upload endpoint with no file field; a file field sent as a regular form field; a request where the file part was dropped by a proxy/CDN due to size limits.","commonSituations":"Frontend uses application/x-www-form-urlencoded instead of multipart/form-data; the file input was left empty and the browser omitted the field; a reverse proxy stripped the multipart file part.","solutions":["Send the request as multipart/form-data with a real file under the \"file\" field.","Ensure the file input has a selected file before submit.","Check proxy/CDN max-body-size settings if large uploads lose their file part."],"exampleFix":"// before\nconst fd = new FormData();\nfd.append('policyName', 'default');\n// missing fd.append('file', ...)\n\n// after\nconst fd = new FormData();\nfd.append('file', selectedFile);\nfd.append('policyName', 'default');","handlingStrategy":"validation","validationCode":"if (!(formData.getFirst(\"file\") instanceof FilePart file)) {\n    return Mono.error(new ServerWebInputException(\"Invalid part of file\"));\n}","typeGuard":"static boolean hasFilePart(MultiValueMap<String, Part> fd) {\n    return fd.getFirst(\"file\") instanceof FilePart;\n}","tryCatchPattern":null,"preventionTips":["Always send the upload as multipart/form-data with a real file under \"file\".","Require a selected file before enabling the upload button.","Check reverse-proxy max body size so the file part isn't dropped."],"tags":["validation","attachment","upload","multipart","http-400"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}