elunez/eladmin · error · BadRequestException

创建存储桶时出错: {}

Error message

创建存储桶时出错: {}

What it means

BadRequestException thrown from createBucket(bucketName) when the bucket-creation flow (CreateBucket + S3Waiter.waitUntilBucketExists) fails with an S3Exception other than BucketAlreadyOwnedByYou. Typical appended details: AccessDenied (no s3:CreateBucket), BucketAlreadyExists (name owned by another account globally), InvalidBucketName, or IllegalLocationConstraint for a wrong-region create.

Source

Thrown at eladmin-tools/src/main/java/me/zhengjie/service/impl/S3StorageServiceImpl.java:260

            S3Waiter s3Waiter = s3Client.waiter();
            CreateBucketRequest bucketRequest = CreateBucketRequest.builder()
                    .bucket(bucketName)
                    .acl(BucketCannedACL.PRIVATE)
                    .build();
            s3Client.createBucket(bucketRequest);
            // 等待直到存储桶创建完成
            HeadBucketRequest bucketRequestWait = HeadBucketRequest.builder()
                    .bucket(bucketName)
                    .build();
            // 使用 WaiterResponse 等待存储桶存在
            WaiterResponse<HeadBucketResponse> waiterResponse = s3Waiter.waitUntilBucketExists(bucketRequestWait);
            waiterResponse.matched().response().ifPresent(response ->
                    log.info("存储桶 '{}' 创建成功,状态: {}", bucketName, response.sdkHttpResponse().statusCode())
            );
        } catch (BucketAlreadyOwnedByYouException e) {
            log.warn("存储桶 '{}' 已经被您拥有,无需重复创建。", bucketName);
        } catch (S3Exception e) {
            throw new BadRequestException("创建存储桶时出错: " + e.awsErrorDetails().errorMessage());
        }
        return true;
    }
}

View on GitHub (pinned to 55fbf70595)

Solutions

  1. Pre-create the bucket manually in the console/MinIO so upload never needs auto-create.
  2. Read the appended AWS message: AccessDenied -> grant s3:CreateBucket; BucketAlreadyExists -> pick a unique name and update config.
  3. Ensure the S3Client's region matches where the bucket may be created (region constraint mismatch raises IllegalLocationConstraint).
  4. For MinIO, follow its bucket-create semantics (region 'us-east-1' default).
  5. Re-run the upload after fixing; createBucket returning true proceeds normally.

Example fix

// before
} catch (S3Exception e) {
    throw new BadRequestException("创建存储桶时出错: " + e.awsErrorDetails().errorMessage());
}
return true;

// after: treat 'already exists elsewhere' distinctly
catch (S3Exception e) {
    if (e.statusCode() == 409) {
        throw new BadRequestException("存储桶名已被其他账户占用,请更换桶名");
    }
    throw new BadRequestException("创建存储桶时出错: " + e.awsErrorDetails().errorMessage());
}
return true;
Defensive patterns

Strategy: fallback

Validate before calling

// prefer explicit pre-creation; only auto-create with a proven-valid name
String bucket = amzS3Config.getDefaultBucket();
if (!bucket.matches("^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$")) {
    throw new BadRequestException("存储桶名称不符合 S3 规范: " + bucket);
}

Try / catch

try { s3StorageService.upload(file); } catch (BadRequestException e) { if (e.getMessage().startsWith("创建存储桶时出错")) { /* fallback: admin creates bucket manually, then retry the upload once */ } }

Prevention

When it happens

Trigger: First upload to a configured-but-missing bucket (see error 91's call site) while: the IAM principal lacks CreateBucket; the name is globally taken (S3 namespace is worldwide); the client's region doesn't match the bucket-location constraint; or a compatible store rejects the create.

Common situations: Least-privilege keys; choosing a generic bucket name like 'my-files' that someone else owns; MinIO endpoints that require a specific LocationConstraint; waiter timing out and surfacing a failure response as S3Exception.

Related errors


AI-assisted analysis of elunez/eladmin@55fbf70595 (2026-08-14). Data as JSON: /api/errors/59a555f99559e3e8. Report an issue: GitHub.