{"record":{"id":"aefa1a448f4e76d3","repo":"apache/druid","slug":"unable-to-move-segment-s-s","errorCode":null,"errorMessage":"Unable to move segment[%s]: [%s]","messagePattern":"Unable to move segment\\[(.+?)\\]: \\[(.+?)\\]","errorType":"exception","errorClass":"SegmentLoadingException","httpStatus":null,"severity":"error","filePath":"extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java","lineNumber":142,"sourceCode":"                          Maps.filterKeys(\n                              loadSpec,\n                              new Predicate<>()\n                              {\n                                @Override\n                                public boolean apply(String input)\n                                {\n                                  return !(\"bucket\".equals(input) || \"key\".equals(input));\n                                }\n                              }\n                          )\n                      )\n                      .put(\"bucket\", targetS3Bucket)\n                      .put(\"key\", targetS3Path)\n                      .build()\n      );\n    }\n    catch (S3Exception e) {\n      throw new SegmentLoadingException(e, \"Unable to move segment[%s]: [%s]\", segment.getId(), e);\n    }\n  }\n\n  private void safeMove(\n      final String s3Bucket,\n      final String s3Path,\n      final String targetS3Bucket,\n      final String targetS3Path\n  ) throws SegmentLoadingException\n  {\n    try {\n      S3Utils.retryS3Operation(\n          () -> {\n            final String copyMsg = StringUtils.format(\n                \"[s3://%s/%s] to [s3://%s/%s]\",\n                s3Bucket,\n                s3Path,\n                targetS3Bucket,","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/extensions-core/s3-extensions/src/main/java/org/apache/druid/storage/s3/S3DataSegmentMover.java#L124-L160","documentation":"Wrapper around any S3Exception raised while performing the actual copy+delete that relocates a segment to the target bucket/key. It carries the segment id and SDK exception so operators can see why the S3 move failed.","triggerScenarios":"After validations pass, safeMove -> moveObject issues copyObject/deleteObject; an S3Exception from the SDK (permissions, throttling, KMS, source gone with no fallback) is caught and rethrown here.","commonSituations":"IAM lacking s3:PutObject on target or s3:DeleteObject on source, cross-region copy denied (CORS/KMS), S3 503 under load, source object deleted concurrently.","solutions":["Read the wrapped S3Exception message/status for the exact S3 error code.","Grant s3:PutObject on the target prefix and s3:DeleteObject on the source prefix.","Match KMS keys/encryption across buckets if SSE is used, or allow cross-key use via key policies.","Retry after throttling errors; reduce move batch size.","Verify source and target buckets are in the region(s) the client can reach."],"exampleFix":"// IAM: allow both directions\n// after: \"Action\": [\"s3:GetObject\",\"s3:PutObject\",\"s3:DeleteObject\"], \"Resource\": [\"arn:aws:s3:::src/*\",\"arn:aws:s3:::dst/*\"]","handlingStrategy":"try-catch","validationCode":"// pre-flight: confirm write access on target\ns3Client.headBucket(HeadBucketRequest.builder().bucket(targetBucket).build());\n// and verify IAM allows s3:PutObject on target prefix via policy simulator","typeGuard":null,"tryCatchPattern":"try { mover.move(segment, target); } catch (SegmentLoadingException e) {\n  if (e.getCause() instanceof S3Exception s3e && s3e.statusCode() == 503) retryWithBackoff();\n  else throw e;\n}","preventionTips":["Grant s3:PutObject on target and s3:DeleteObject on source","Use same-region or same-KMS-key buckets to avoid copy restrictions","Batch moves conservatively to avoid S3 throttling"],"tags":["aws","s3","segment-move","s3exception"],"backgroundTag":"http-error-response","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}