{"record":{"id":"31004f29ad2b606d","repo":"apache/flink","slug":"failed-to-upload-part-d-for-key-s-uploadid-s","errorCode":null,"errorMessage":"Failed to upload part %d for key: %s, uploadId: %s","messagePattern":"Failed to upload part (.+?) for key: (.+?), uploadId: (.+?)","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/writer/NativeS3ObjectOperations.java","lineNumber":200,"sourceCode":"\n    public UploadPartResult uploadPart(\n            String key, String uploadId, int partNumber, File inputFile, long length)\n            throws IOException {\n        try {\n            UploadPartRequest request =\n                    UploadPartRequest.builder()\n                            .bucket(bucketName)\n                            .key(key)\n                            .uploadId(uploadId)\n                            .partNumber(partNumber)\n                            .build();\n\n            UploadPartResponse response =\n                    s3Client.uploadPart(request, RequestBody.fromFile(inputFile));\n\n            return new UploadPartResult(partNumber, response.eTag());\n        } catch (S3Exception e) {\n            throw new IOException(\n                    String.format(\n                            \"Failed to upload part %d for key: %s, uploadId: %s\",\n                            partNumber, key, uploadId),\n                    e);\n        }\n    }\n\n    public PutObjectResult putObject(String key, File inputFile) throws IOException {\n        if (useAsyncOperations && transferManager != null) {\n            return putObjectViaTransferManager(key, inputFile);\n        }\n\n        try {\n            PutObjectRequest.Builder requestBuilder =\n                    PutObjectRequest.builder().bucket(bucketName).key(key);\n            applyEncryption(requestBuilder);\n\n            PutObjectResponse response =","sourceCodeStart":182,"sourceCodeEnd":218,"githubUrl":"https://github.com/apache/flink/blob/2f3c205e9266cb30240eb7f4fdab15cad629a70f/flink-filesystems/flink-s3-fs-native/src/main/java/org/apache/flink/fs/s3native/writer/NativeS3ObjectOperations.java#L182-L218","documentation":"uploadPart() sends one already-materialized part file (RequestBody.fromFile) as UploadPart with a given partNumber and uploadId, returning the part's eTag for later CompleteMultipartUpload. Any S3Exception during the call is wrapped into this formatted IOException including part number, key and uploadId — the three identifiers needed to either retry the single part or abort the upload.","triggerScenarios":"Network interruption or 5xx/SlowDown during upload of a large part (default part sizes are multi-MB); credentials expiring mid-upload (session/STS); uploadId already aborted/completed (NoSuchUpload surfaces here if a sibling attempt finished it); throttling on high-parallelism part uploads; part file deleted locally before the call reads it (non-S3 error would differ, but fromFile read failure can surface inside).","commonSituations":"Long checkpoint uploads where STS session expires halfway; too many concurrent streams overwhelming connection pool causing timeouts; transient AWS-side throttling during mass recovery; recovery races where another attempt aborted the upload.","solutions":["Retry the whole recoverable upload: Flink's writer semantics allow re-uploading the same part number with a new etag — or better, recover via the RecoverableWriter which re-uploads from the persisted offset.","If cause is NoSuchUpload, restart from a fresh startMultiPartUpload (the old upload was completed/aborted by another attempt).","For SlowDown/503: reduce fs.s3.limit.outside/inside? — concretely lower writer parallelism or part-upload concurrency and ensure fs.s3.connection.maximum is sized for parallel parts.","For expired credentials: use a credentials provider that refreshes (instance profile / DynamicTemporaryAWSCredentialsProvider) instead of static keys."],"exampleFix":"// before — one-shot part upload with no retry\nUploadPartResult r = ops.uploadPart(key, uploadId, partNumber, file);\n\n// after — retry the individual part (same partNumber is safe; a new etag supersedes)\nUploadPartResult r = retryOnS3Transient(\n    () -> ops.uploadPart(key, uploadId, partNumber, file),\n    5, Duration.ofSeconds(2));","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"catch (IOException e) {\n    Throwable c = e.getCause();\n    if (c instanceof NoSuchUploadException) { restartUploadFromScratch(); }\n    else if (c instanceof S3Exception && ((S3Exception) c).statusCode() >= 500) { retrySamePartWithBackoff(); } // same partNumber supersedes prior etag\n    else throw e;\n}","preventionTips":["Retry the same partNumber on transient failures — S3 lets a re-upload supersede the old etag.","Use refreshing credentials providers for long uploads so sessions do not expire mid-part.","Size fs.s3.connection.maximum for your writer parallelism to avoid acquisition timeouts."],"tags":["s3","multipart-upload","network","retry","credentials","flink"],"backgroundTag":null,"analyzedSha":"2f3c205e9266cb30240eb7f4fdab15cad629a70f","analyzedAt":"2026-08-14T08:48:24.518Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}