{"record":{"id":"2cd0deecf849e059","repo":"apache/druid","slug":"target-s3-basekey-is-not-specified","errorCode":null,"errorMessage":"Target S3 baseKey is not specified","messagePattern":"Target S3 baseKey is not specified","errorType":"exception","errorClass":"SegmentLoadingException","httpStatus":null,"severity":"error","filePath":"extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java","lineNumber":100,"sourceCode":"\n      if (s3Path.endsWith(\"/\")) {\n        // segment is not compressed, list objects and move them all\n        ListObjectsV2Request request = ListObjectsV2Request.builder()\n            .bucket(s3Bucket)\n            .prefix(s3Path + \"/\")\n            .build();\n        final ListObjectsV2Response list = s3ClientSupplier.get().listObjectsV2(request);\n        targetS3Path = S3Utils.constructSegmentBasePath(\n            targetS3BaseKey,\n            DataSegmentPusher.getDefaultStorageDir(segment, false)\n        );\n        for (S3Object objectSummary : list.contents()) {\n          final String fileName = Paths.get(objectSummary.key()).getFileName().toString();\n          if (targetS3Bucket.isEmpty()) {\n            throw new SegmentLoadingException(\"Target S3 bucket is not specified\");\n          }\n          if (targetS3Path.isEmpty()) {\n            throw new SegmentLoadingException(\"Target S3 baseKey is not specified\");\n          }\n\n          safeMove(s3Bucket, s3Path, targetS3Bucket, targetS3Path + \"/\" + fileName);\n        }\n      } else {\n        targetS3Path = S3Utils.constructSegmentPath(\n            targetS3BaseKey,\n            DataSegmentPusher.getDefaultStorageDir(segment, false)\n        );\n\n        if (targetS3Bucket.isEmpty()) {\n          throw new SegmentLoadingException(\"Target S3 bucket is not specified\");\n        }\n        if (targetS3Path.isEmpty()) {\n          throw new SegmentLoadingException(\"Target S3 baseKey is not specified\");\n        }\n\n        safeMove(s3Bucket, s3Path, targetS3Bucket, targetS3Path);","sourceCodeStart":82,"sourceCodeEnd":118,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java#L82-L118","documentation":"Same validation as the bucket check, but for the target base key: when moving within derived path mode, an empty targetS3Path means the move payload lacks the destination prefix, so the move cannot proceed.","triggerScenarios":"move() with DataSegment_move whose baseKey resolves to empty string, detected inside the list-contents loop before safeMove is executed.","commonSituations":"Move request sent with bucket set but baseKey omitted or blank string; scripting error building the move task payload.","solutions":["Provide a non-empty \"baseKey\" in the DataSegment_move target loadSpec.","Re-issue the move operation after correcting the payload.","Add client-side validation that both bucket and baseKey are non-empty before submitting moves."],"exampleFix":"// before: move target baseKey \"\"\n// after: {\"bucket\":\"target-bucket\",\"baseKey\":\"druid/segments\"}","handlingStrategy":"validation","validationCode":"if (target == null || target.getBaseKey() == null || target.getBaseKey().isEmpty()) {\n  throw new IllegalArgumentException(\"DataSegment_move requires non-empty baseKey\");\n}","typeGuard":null,"tryCatchPattern":"try { mover.move(segment, target); } catch (SegmentLoadingException e) { resubmitWithBaseKey(); }","preventionTips":["Never submit move targets with empty-string baseKey","Add schema validation on move task payloads","Keep a standard default prefix (e.g. druid/segments) in move tooling"],"tags":["s3","segment-move","config","validation"],"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-14T05:17:10.506Z"}