apache/hadoop · critical · IOException

Multipart upload incomplete: expected {} parts but got {}

Error message

Multipart upload incomplete: expected {} parts but got {}

What it means

After close() waits for all part threads, it compares the collected eTags count against blkIndex - 1 (blocks uploaded). A mismatch means some thread finished without recording an ETag — a silent or lost failure with no uploadException — so completeMultipartUpload cannot be issued. The upload is aborted server-side and IOException 'Multipart upload incomplete: expected N parts but got M' is thrown; like error 37, no object is created.

Source

Thrown at hadoop-cloud-storage-project/hadoop-bos/src/main/java/org/apache/hadoop/fs/bos/BosOutputStream.java:417

            e);
      }

      if (uploadException != null) {
        abortMultipartUpload();
        throw new IOException(
            "Multipart upload failed", uploadException);
      }

      LOG.debug(
          "success to wait upload part threads done");

      LOG.debug(
          "Size of eTags is {}. blkIndex is {}",
          this.eTags.size(), this.blkIndex);

      if (this.eTags.size() != this.blkIndex - 1) {
        abortMultipartUpload();
        throw new IOException(
            "Multipart upload incomplete: expected "
                + (this.blkIndex - 1) + " parts but got "
                + this.eTags.size());
      }

      completeMultipartUpload(
          bucketName, this.key,
          this.uploadId, this.eTags);
    }

    super.close();
    this.closed = true;
  }

  /**
   * Aborts the in-progress multipart upload to prevent
   * storage leakage on failure.
   */

View on GitHub (pinned to 2add963021)

Solutions

  1. Scan the preceding logs for interrupted or failed upload threads — something silently dropped a part result
  2. Ensure close() runs on a healthy, non-interrupted thread; avoid killing tasks during their commit phase
  3. Retry the write from scratch; the abort guarantees no partial object remains
  4. Upgrade the connector if a known eTag-collection race is fixed in a newer hadoop-bos version
Defensive patterns

Strategy: retry

Type guard

static boolean isMultipartIncomplete(IOException e) {
  return e.getMessage() != null && e.getMessage().startsWith("Multipart upload incomplete");
}

Try / catch

catch (IOException e) {
  if (isMultipartIncomplete(e)) {
    // silent part loss: retry the whole write; ensure close() is not interrupted
    rewriteFromSource(path);
  } else { throw e; }
}

Prevention

When it happens

Trigger: An upload thread ends without propagating its exception or its ETag: task cancellation racing close(), JVM/thread-pool shutdown during commit, or a race in result collection after an earlier swallowed InterruptedException in the wait loop.

Common situations: Forcible task kill or speculation cancellation exactly at commit time; executor shutdown hooks closing streams on an interrupted thread; usually preceded by interrupt/timeout warnings in the logs.

Related errors


AI-assisted analysis of apache/hadoop@2add963021 (2026-08-22). Data as JSON: /api/errors/b674758351b6b080. Report an issue: GitHub.