{"record":{"id":"3be2a2c8923ca804","repo":"elunez/eladmin","slug":"error-3be2a2","errorCode":null,"errorMessage":"存储桶创建失败，请检查配置或权限。","messagePattern":"存储桶创建失败，请检查配置或权限。","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"eladmin-tools/src/main/java/me/zhengjie/service/impl/S3StorageServiceImpl.java","lineNumber":118,"sourceCode":"                // 删除数据库数据\n                s3StorageRepository.deleteById(id);\n            } catch (S3Exception e) {\n                // 处理 AWS 特定的异常\n                log.error(\"从 S3 删除文件时出错: {}\", e.awsErrorDetails().errorMessage(), e);\n            }\n        }\n    }\n\n    @Override\n    public S3Storage upload(MultipartFile file) {\n        String bucketName = amzS3Config.getDefaultBucket();\n        // 检查存储桶是否存在\n        if (!bucketExists(bucketName)) {\n            log.warn(\"存储桶 {} 不存在，尝试创建...\", bucketName);\n            if (createBucket(bucketName)){\n                log.info(\"存储桶 {} 创建成功。\", bucketName);\n            } else {\n                throw new BadRequestException(\"存储桶创建失败，请检查配置或权限。\");\n            }\n        }\n        // 获取文件名\n        String originalName = file.getOriginalFilename();\n        if (StringUtils.isBlank(originalName)) {\n            throw new IllegalArgumentException(\"文件名不能为空\");\n        }\n        // 生成存储路径和文件名\n        String folder = DateUtil.format(new Date(), amzS3Config.getTimeformat());\n        String fileName = IdUtil.simpleUUID() + \".\" + FileUtil.getExtensionName(originalName);\n        String filePath = folder + \"/\" + fileName;\n        // 构建上传请求\n        PutObjectRequest putObjectRequest = PutObjectRequest.builder()\n                .bucket(amzS3Config.getDefaultBucket())\n                .key(filePath)\n                .build();\n        // 创建 S3Storage 实例\n        S3Storage s3Storage = new S3Storage();","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/elunez/eladmin/blob/55fbf705956949697dbd68bf9003776609d3d029/eladmin-tools/src/main/java/me/zhengjie/service/impl/S3StorageServiceImpl.java#L100-L136","documentation":"Thrown by S3StorageServiceImpl.upload when the default bucket does not exist AND the auto-create attempt (createBucket, which waits via S3Waiter.waitUntilBucketExists) returned false / threw a non-BucketOwned S3Exception. So both the head-bucket miss and the create-bucket path failed — typically missing s3:CreateBucket permission, an invalid bucket name, or an endpoint that rejects creation.","triggerScenarios":"POST the S3 upload endpoint with amzS3Config.defaultBucket pointing at a nonexistent bucket while the configured IAM user lacks CreateBucket permission (403), or the bucket name violates S3 naming rules (uppercase, underscore, too long) so createBucket errors; also MinIO/compatible endpoints where the waiter times out.","commonSituations":"Least-privilege IAM policy with only PutObject/GetObject; typo'd bucket name that is also invalid as a new name; region-restricted create permissions; restricted on-prem S3 gateway that forbids client-side bucket creation.","solutions":["Pre-create the bucket in the S3 console / MinIO and re-upload — removes reliance on auto-create.","Grant s3:CreateBucket (and s3:HeadBucket) to the configured credentials if auto-create is desired.","Correct the bucket name in config to valid S3 naming (lowercase, no underscores, 3-63 chars).","Check createBucket logs for the waiter failure or the S3Exception detail (error 97 surfaces that message).","For S3-compatible stores, confirm the endpoint allows bucket creation APIs."],"exampleFix":"// before\nif (createBucket(bucketName)){\n    log.info(\"存储桶 {} 创建成功。\", bucketName);\n} else {\n    throw new BadRequestException(\"存储桶创建失败，请检查配置或权限。\");\n}\n\n// after: fail fast with the IAM expectation made explicit\nif (!bucketExists(bucketName) && !createBucket(bucketName)) {\n    throw new BadRequestException(\"存储桶 \" + bucketName + \" 创建失败：请确认凭证具有 s3:CreateBucket 权限或先手动创建该桶\");\n}","handlingStrategy":"fallback","validationCode":"// pre-create the bucket (idempotent) before enabling uploads\nString bucket = amzS3Config.getDefaultBucket();\nif (!bucketExists(bucket) && !createBucket(bucket)) {\n    throw new BadRequestException(\"请先手动创建存储桶 \" + bucket);\n}","typeGuard":null,"tryCatchPattern":"try { s3StorageService.upload(file); } catch (BadRequestException e) { if (e.getMessage().contains(\"存储桶创建失败\")) { /* fallback: create bucket out-of-band, then retry upload once */ } }","preventionTips":["Pre-create buckets during environment provisioning instead of relying on upload-time auto-create.","Grant s3:CreateBucket + s3:HeadBucket to the service credentials if auto-create is kept.","Use S3-valid bucket names (lowercase, 3-63 chars) when configuring."],"tags":["s3","bucket-creation","iam","permissions","aws-sdk-v2"],"backgroundTag":null,"analyzedSha":"55fbf705956949697dbd68bf9003776609d3d029","analyzedAt":"2026-08-14T11:56:12.758Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}