{"record":{"id":"607501be043434fa","repo":"apache/flink","slug":"failed-to-rename-to","errorCode":null,"errorMessage":"Failed to rename {} to {}","messagePattern":"Failed to rename (.+?) to (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/NativeS3FileSystem.java","lineNumber":492,"sourceCode":"            throw new UnsupportedOperationException(\n                    \"NativeS3FileSystem does not support renaming directories: \" + src);\n        }\n\n        try {\n            final CopyObjectRequest copyRequest =\n                    CopyObjectRequest.builder()\n                            .sourceBucket(bucketName)\n                            .sourceKey(srcKey)\n                            .destinationBucket(bucketName)\n                            .destinationKey(dstKey)\n                            .build();\n            s3Client.copyObject(copyRequest);\n            final DeleteObjectRequest deleteRequest =\n                    DeleteObjectRequest.builder().bucket(bucketName).key(srcKey).build();\n            s3Client.deleteObject(deleteRequest);\n            return true;\n        } catch (S3Exception e) {\n            throw new IOException(\"Failed to rename \" + src + \" to \" + dst, e);\n        }\n    }\n\n    @Override\n    public boolean isDistributedFS() {\n        return true;\n    }\n\n    @Nullable\n    @Override\n    public String getEntropyInjectionKey() {\n        return entropyInjectionKey;\n    }\n\n    @Override\n    public String generateEntropy() {\n        return StringUtils.generateRandomAlphanumericString(\n                ThreadLocalRandom.current(), entropyLength);","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/NativeS3FileSystem.java#L474-L510","documentation":"Rename is implemented as copyObject followed by deleteObject on the same bucket. Any AWS SDK S3Exception from either call is wrapped in IOException('Failed to rename <src> to <dst>') with the cause preserved. Common causes are access denied on the source key, missing s3:PutObject at the destination, KMS/SSE permission issues on copy, or the source vanishing mid-rename.","triggerScenarios":"rename(src, dst) on an existing object when copyObject or deleteObject fails — 403 (missing s3:GetObject/s3:PutObject/s3:DeleteObject), SSE-KMS key not usable, source deleted concurrently, or transient S3 errors.","commonSituations":"IAM roles without copy/delete permissions; cross-account buckets; KMS key policy not granting decrypt to the writer; racing cleanup jobs deleting the source between status check and copy.","solutions":["Inspect the wrapped S3Exception status code and grant the needed s3:GetObject, s3:PutObject, s3:DeleteObject (and kms:Decrypt/GenerateDataKey for SSE-KMS copy) permissions.","Handle the race: catch IOException, re-check exists(src), and treat a missing source as success or skip.","For transient 5xx causes, retry rename with backoff — copyObject+deleteObject is safe to retry if the copy is idempotent for your use case."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    s3Fs.rename(src, dst);\n} catch (IOException e) {\n    if (e.getCause() instanceof S3Exception) {\n        S3Exception s3e = (S3Exception) e.getCause();\n        if (s3e.statusCode() >= 500) {\n            // transient: retry copyObject+deleteObject with backoff\n        } else if (!s3Fs.exists(src)) {\n            // source vanished mid-rename: treat as moved/skip\n        } else {\n            // permissions/SSE issue surfaced by s3e: fix IAM/KMS before retrying\n        }\n    } else {\n        throw e;\n    }\n}","preventionTips":["Verify the role has s3:GetObject, s3:PutObject, s3:DeleteObject before using rename.","For SSE-KMS buckets, ensure kms:Decrypt/GenerateDataKey rights for the copy step.","Remember S3 rename is copy+delete — not atomic — design commit logic accordingly."],"tags":["s3","rename","permissions","aws-sdk"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}