apache/hadoop · error · RuntimeException
parts length mismatched: %d != %d
Error message
parts length mismatched: %d != %d
What it means
FileStore.completeUpload() counts the part files present in the upload's staging directory and compares against the uploadParts list handed in; if the counts differ it throws 'parts length mismatched'. The caller's part list and the parts actually staged on disk no longer describe the same upload — parts are missing from the list, or the directory holds extra/stale part files.
Source
Thrown at hadoop-cloud-storage-project/hadoop-tos/src/main/java/org/apache/hadoop/fs/tosfs/object/FileStore.java:414
}
if (!tmpFile.renameTo(partFile)) {
throw new RuntimeException("failed to put file since rename fail.");
}
}
@Override
public byte[] completeUpload(String key, String uploadId, List<Part> uploadParts) {
Preconditions.checkArgument(uploadParts != null && uploadParts.size() > 0,
"upload parts cannot be null or empty.");
File uploadDir = uploadPath(key, uploadId).toFile();
if (!uploadDir.exists()) {
throw new RuntimeException("cannot locate the upload id: " + uploadId);
}
List<Integer> partNums = listPartNums(uploadDir);
if (partNums.size() != uploadParts.size()) {
throw new RuntimeException(String.format("parts length mismatched: %d != %d",
partNums.size(), uploadParts.size()));
}
Collections.sort(partNums);
uploadParts.sort(Comparator.comparingInt(Part::num));
Path keyPath = path(encode(key));
File tmpFile = createTmpFile(keyPath.toFile());
try (FileOutputStream outputStream = new FileOutputStream(tmpFile);
FileChannel outputChannel = outputStream.getChannel()) {
int offset = 0;
for (int i = 0; i < partNums.size(); i++) {
Part part = uploadParts.get(i);
if (part.num() != partNums.get(i)) {
throw new RuntimeException(
String.format("part num mismatched: %d != %d", part.num(), partNums.get(i)));
}
View on GitHub (pinned to 2add963021)
Solutions
- Build the parts list exclusively from the Part objects returned by uploadPart()/uploadPartCopy() and pass that exact list to completeUpload
- Ensure every part upload succeeded (collect and check results) before completing
- Never modify or prune files inside __STAGING__/<key>/<uploadId> by hand; if the dir is suspect, abort the upload and start a new one
- Give each concurrent writer its own uploadId via createMultipartUpload instead of sharing one
Example fix
// before: hand-built parts list that lost part 1
List<Part> parts = List.of(new Part(2, len2, etag2)); // parts length mismatched: 1 != 2
// after: collect exactly what uploadPart returned, in upload order
List<Part> parts = new ArrayList<>();
for (int n = 1; n <= totalParts; n++) {
parts.add(storage.uploadPart(key, uploadId, n, providerFor(n), lenFor(n)));
}
storage.completeUpload(key, uploadId, parts); Defensive patterns
Strategy: validation
Validate before calling
List<Part> parts = new ArrayList<>();
for (int n = 1; n <= totalParts; n++) {
Part p = storage.uploadPart(key, uploadId, n, providerFor(n), lenFor(n));
if (p == null) throw new IOException("part " + n + " not uploaded");
parts.add(p);
}
if (parts.size() != totalParts) {
throw new IOException("staged " + parts.size() + " parts, expected " + totalParts);
}
storage.completeUpload(key, uploadId, parts); Prevention
- Build the parts list only from Part objects returned by uploadPart/uploadPartCopy
- Check every part-upload result before completing; a silently skipped part guarantees this failure
- Never let tests or scripts add/remove files inside __STAGING__/<key>/<uploadId>
- Isolate concurrent writers with distinct uploadIds (createMultipartUpload per writer)
When it happens
Trigger: completeUpload where some uploadPart call never ran or failed silently, a part file was deleted from the staging dir, stale part files from an earlier numbering scheme linger, or the caller hand-built the parts list instead of using the Part objects returned by uploadPart().
Common situations: Loop that uploads parts but drops one on an exception path; retry frameworks that re-run a subset of parts; tests listing part files manually; concurrent writers sharing an uploadId.
Related errors
- part num mismatched: %d != %d
- part size mismatched: %d != %d
- part etag mismatched: %s != %s
- Failed to create MultipartUpload with key: %s
- cannot locate the upload id: %s
AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22).
Data as JSON: /api/errors/bc94ac7ac02f4c76.
Report an issue: GitHub.