{"record":{"id":"d21e28fce7eea0aa","repo":"elunez/eladmin","slug":"error-d21e28","errorCode":null,"errorMessage":"上传失败","messagePattern":"上传失败","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"eladmin-tools/src/main/java/me/zhengjie/service/impl/LocalStorageServiceImpl.java","lineNumber":80,"sourceCode":"        return localStorageMapper.toDto(localStorageRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder)));\n    }\n\n    @Override\n    public LocalStorageDto findById(Long id){\n        LocalStorage localStorage = localStorageRepository.findById(id).orElseGet(LocalStorage::new);\n        ValidationUtil.isNull(localStorage.getId(),\"LocalStorage\",\"id\",id);\n        return localStorageMapper.toDto(localStorage);\n    }\n\n    @Override\n    @Transactional(rollbackFor = Exception.class)\n    public LocalStorage create(String name, MultipartFile multipartFile) {\n        FileUtil.checkSize(properties.getMaxSize(), multipartFile.getSize());\n        String suffix = FileUtil.getExtensionName(multipartFile.getOriginalFilename());\n        String type = FileUtil.getFileType(suffix);\n        File file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type +  File.separator);\n        if(ObjectUtil.isNull(file)){\n            throw new BadRequestException(\"上传失败\");\n        }\n        try {\n            name = StringUtils.isBlank(name) ? FileUtil.getFileNameNoEx(multipartFile.getOriginalFilename()) : name;\n            LocalStorage localStorage = new LocalStorage(\n                    file.getName(),\n                    name,\n                    suffix,\n                    file.getPath(),\n                    type,\n                    FileUtil.getSize(multipartFile.getSize())\n            );\n            return localStorageRepository.save(localStorage);\n        }catch (Exception e){\n            FileUtil.del(file);\n            throw e;\n        }\n    }\n","sourceCodeStart":62,"sourceCodeEnd":98,"githubUrl":"https://github.com/elunez/eladmin/blob/55fbf705956949697dbd68bf9003776609d3d029/eladmin-tools/src/main/java/me/zhengjie/service/impl/LocalStorageServiceImpl.java#L62-L98","documentation":"Thrown by LocalStorageServiceImpl.create when FileUtil.upload(multipartFile, path) returns null after the size check passed — hutool's FileUtil.upload returns null on IOException while writing the multipart file to disk under properties.getPath().getPath() + type + separator. So the file exceeded maxSize it would have thrown earlier (a different exception); this specific error means a disk-level write failure.","triggerScenarios":"POST /localStorage (file upload) or POST /localStorage/pictures where the target directory configured by LocalStorage properties (files.path) does not exist or is not writable; disk full; container read-only filesystem; path with insufficient permissions for the JVM user.","commonSituations":"Default './file' path not created in the deployment dir; Docker image running as non-root with no write access to the mounted volume; disk quota exhausted; SELinux denying writes; path property changed to a location that isn't mounted.","solutions":["Check the configured storage path (LocalStorage properties, e.g. files.path in application.yml) exists and is writable by the JVM process user (touch test).","Free disk space / raise quota if the volume is full (df -h).","In containers, mount a writable volume at the configured path and ensure the run user owns it.","Confirm directory creation: FileUtil.upload expects the base type directories to be creatable — pre-create `<path>/image`, `<path>/doc`, etc. or grant mkdir rights.","Inspect logs for the underlying IOException swallowed by FileUtil.upload's null return."],"exampleFix":"// before\nFile file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type + File.separator);\nif(ObjectUtil.isNull(file)){\n    throw new BadRequestException(\"上传失败\");\n}\n\n// after: write explicitly and fail with the real cause\nFile dir = new File(properties.getPath().getPath(), type);\nif(!dir.exists() && !dir.mkdirs()){\n    throw new BadRequestException(\"存储目录创建失败: \" + dir.getAbsolutePath());\n}\nFile file = null;\ntry {\n    file = new File(dir, IdUtil.simpleUUID() + \".\" + suffix);\n    multipartFile.transferTo(file);\n} catch (IOException e) {\n    throw new BadRequestException(\"上传失败: \" + e.getMessage());\n}","handlingStrategy":"validation","validationCode":"// startup sanity: storage root must be writable\nFile root = new File(properties.getPath().getPath());\nif (!root.exists() && !root.mkdirs()) throw new IllegalStateException(\"storage path not creatable: \" + root);\nif (!root.canWrite()) throw new IllegalStateException(\"storage path not writable: \" + root);","typeGuard":null,"tryCatchPattern":"try { localStorageService.create(name, file); } catch (BadRequestException e) { if (\"上传失败\".equals(e.getMessage())) { /* disk/permission issue: check volume, do not retry the same upload blindly */ } }","preventionTips":["Mount a writable volume at the configured files.path in containers and chown it to the run user.","Disk-space alerts on the storage volume — FileUtil.upload returns null on IO failure.","Pre-create type subdirectories (image/doc/media/...) at deploy time."],"tags":["file-upload","local-storage","disk","permissions","io"],"backgroundTag":null,"analyzedSha":"55fbf705956949697dbd68bf9003776609d3d029","analyzedAt":"2026-08-14T11:56:12.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}