{"record":{"id":"a74ee347b772a2bb","repo":"halo-dev/halo","slug":"only-support-file-with-extension","errorCode":null,"errorMessage":"Only support file with extension: {}","messagePattern":"Only support file with extension: (.+?)","errorType":"validation","errorClass":"ServerWebInputException","httpStatus":400,"severity":"error","filePath":"application/src/main/java/run/halo/app/core/endpoint/console/UserEndpoint.java","lineNumber":412,"sourceCode":"        FilePart getFile();\n    }\n\n    public record AvatarUploadRequest(MultiValueMap<String, Part> formData) {\n        public FilePart getFile() {\n            Part file = formData.getFirst(\"file\");\n            if (file == null) {\n                throw new ServerWebInputException(\"No file part found in the request\");\n            }\n\n            if (!(file instanceof FilePart filePart)) {\n                throw new ServerWebInputException(\"Invalid part of file\");\n            }\n\n            boolean isNoneExt = Arrays.stream(ALLOWED_AVATAR_EXTENSIONS)\n                    .noneMatch(ext -> filePart.filename().endsWith(\".\" + ext));\n\n            if (isNoneExt) {\n                throw new ServerWebInputException(\n                        \"Only support file with extension: \" + String.join(\", \", ALLOWED_AVATAR_EXTENSIONS));\n            }\n            return filePart;\n        }\n    }\n\n    private Mono<Attachment> uploadAvatar(AvatarUploadRequest uploadRequest) {\n        var fallbackSetting = environmentFetcher\n                .fetch(SystemSetting.User.GROUP, SystemSetting.User.class)\n                .mapNotNull(SystemSetting.User::getAvatarPolicy)\n                .filter(StringUtils::isNotBlank);\n        var getAvatarPolicy = environmentFetcher\n                .fetch(SystemSetting.Attachment.GROUP, SystemSetting.Attachment.class)\n                .mapNotNull(SystemSetting.Attachment::avatar)\n                .mapNotNull(UploadOptions::policyName)\n                .filter(StringUtils::isNotBlank)\n                .switchIfEmpty(fallbackSetting)\n                .defaultIfEmpty(DEFAULT_USER_AVATAR_ATTACHMENT_POLICY_NAME);","sourceCodeStart":394,"sourceCodeEnd":430,"githubUrl":"https://github.com/halo-dev/halo/blob/d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8/application/src/main/java/run/halo/app/core/endpoint/console/UserEndpoint.java#L394-L430","documentation":"Thrown as a ServerWebInputException (HTTP 400) by AvatarUploadRequest.getFile() when the uploaded file's extension is not in ALLOWED_AVATAR_EXTENSIONS. The message interpolates the allowed list (e.g. png, jpg, jpeg, gif, webp) so the caller knows what is accepted.","triggerScenarios":"POST to the avatar upload endpoint with a file whose extension is not in the allow-list — e.g. .bmp, .svg, .tif, .heic, or a file with no extension. The check is a simple endsWith so a missing dot also fails.","commonSituations":"User picks a HEIC photo from a phone; SVG intended as a logo; screenshot saved as .bmp; filename lost its extension during transfer; admin wants a format not in the default allow-list.","solutions":["Convert the image to one of the allowed formats (png/jpg/jpeg/gif/webp) before uploading.","Rename the file to use an allowed extension only if the actual content matches that format.","If a new format is genuinely required, extend ALLOWED_AVATAR_EXTENSIONS and ensure the storage/attachment policy supports it."],"exampleFix":"// before: upload avatar.bmp\n// after:  convert to png, upload avatar.png","handlingStrategy":"validation","validationCode":"// check extension against the allow-list before upload\nSet<String> allowed = Set.of(\"png\", \"jpg\", \"jpeg\", \"gif\", \"webp\");\nString ext = name.substring(name.lastIndexOf('.') + 1).toLowerCase(Locale.ROOT);\nif (!allowed.contains(ext)) {\n    showUserError(\"Allowed: \" + allowed);\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set the file input accept='.png,.jpg,.jpeg,.gif,.webp'.","Convert/resize images to an allowed format before upload."],"tags":["user","avatar","upload","validation","file-extension"],"backgroundTag":null,"analyzedSha":"d2f5165f9c8f055ffcb3fa9c3f4032821a7b68c8","analyzedAt":"2026-08-14T00:18:38.915Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}