{"record":{"id":"c418a3dfc620c1a7","repo":"apache/druid","slug":"s3client-supplier-cannot-be-null","errorCode":null,"errorMessage":"S3Client supplier cannot be null!","messagePattern":"S3Client supplier cannot be null!","errorType":"validation","errorClass":"IllegalStateException (ISE)","httpStatus":null,"severity":"error","filePath":"extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/ServerSideEncryptingAmazonS3.java","lineNumber":543,"sourceCode":"    }\n\n    /**\n     * Builds a new {@link ServerSideEncryptingAmazonS3} instance.\n     *\n     * <p><b>Resource leak warning:</b> Each instance created by this method holds internal resources such as thread\n     * pools and connection pools. {@link ServerSideEncryptingAmazonS3} is not {@link java.io.Closeable}, so there is\n     * currently no way for callers to release these resources when the instance is no longer needed. Avoid calling\n     * this method repeatedly (e.g., once per file or per task) when a single shared instance would suffice. Consider\n     * memoizing the result, as {@link org.apache.druid.data.input.s3.S3InputSource} does, to ensure the client is\n     * created at most once per configuration.\n     *\n     * <p>The long-term fix is to make {@link ServerSideEncryptingAmazonS3} implement {@link java.io.Closeable} and\n     * arrange for {@code close()} to be called appropriately, but that is a larger change deferred for the future.\n     */\n    public ServerSideEncryptingAmazonS3 build()\n    {\n      if (s3ClientSupplier == null) {\n        throw new ISE(\"S3Client supplier cannot be null!\");\n      }\n      if (s3StorageConfig == null) {\n        throw new ISE(\"S3StorageConfig cannot be null!\");\n      }\n\n      S3Client s3Client;\n      try {\n        s3Client = S3Utils.retryS3Operation(s3ClientSupplier::get);\n      }\n      catch (Exception e) {\n        throw new RuntimeException(e);\n      }\n\n      S3AsyncClient s3AsyncClient = null;\n      if (s3AsyncClientSupplier != null) {\n        try {\n          s3AsyncClient = S3Utils.retryS3Operation(s3AsyncClientSupplier::get);\n        }","sourceCodeStart":525,"sourceCodeEnd":561,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/ServerSideEncryptingAmazonS3.java#L525-L561","documentation":"The ServerSideEncryptingAmazonS3.Builder.build() requires an S3Client supplier to have been set (via s3Client(...) / setS3ClientSupplier). Throwing ISE guards against constructing the encrypting client wrapper with no underlying client factory.","triggerScenarios":"Calling builder.build() without first invoking s3ClientSupplier(...), typically in custom extension code or tests wiring ServerSideEncryptingAmazonS3 manually.","commonSituations":"Hand-rolled module/Google Guice bindings copying an outdated example; tests constructing the builder but forgetting the supplier step; refactors that renamed the setter.","solutions":["Call builder.s3ClientSupplier(() -> S3Client.builder().build()) before build().","Use AWSClientUtil-provided client configuration helpers to build the supplier.","Also ensure s3StorageConfig(...) is set, the next required field.","Update custom wiring to match the current S3StorageDruidModule setup."],"exampleFix":"// before\nServerSideEncryptingAmazonS3 s3 = new ServerSideEncryptingAmazonS3.Builder().build();\n// after\nServerSideEncryptingAmazonS3 s3 = new ServerSideEncryptingAmazonS3.Builder()\n    .s3ClientSupplier(() -> S3Client.create())\n    .s3StorageConfig(new S3StorageConfig(ImmutableList.of()))\n    .build();","handlingStrategy":"validation","validationCode":"if (builder == null) throw new IllegalArgumentException(\"builder required\");\n// ensure supplier set before build:\n// builder.s3ClientSupplier(...) must have been called","typeGuard":null,"tryCatchPattern":"try { s3 = builder.build(); } catch (IllegalStateException e) { throw new IllegalStateException(\"wire s3ClientSupplier/s3StorageConfig before build()\", e); }","preventionTips":["Always set s3ClientSupplier and s3StorageConfig before build()","Copy wiring from the current S3StorageDruidModule","Add unit tests constructing the builder end-to-end"],"tags":["s3","builder","misuse","internal"],"backgroundTag":"missing-required-argument","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}