hashicorp/terraform · error

not all parts uploaded successfully, multipart upload…

Error message

not all parts uploaded successfully, multipart upload aborted

What it means

A count check: if len(commitMultipartUploadPartDetails) != len(sourceBlocks), the code aborts the multipart upload and returns this error. The mismatch happens when one or more workers exited via errChan (sending a non-nil error) instead of pushing a response — so the responses channel has fewer entries than source blocks. Note: the per-worker error was already drained from errChan at lines 117-121 and would have returned earlier; reaching 318 means errChan was empty but responses were still short (e.g. a worker that errored AND the loop at 117 returned nil entries, or a worker that exited without sending to either channel on a panic).

Solutions

  1. Resolve underlying part-upload failures (see 317) — run with TF_LOG=DEBUG to find which worker errored.
  2. Verify the abort succeeded — if AbortMultipartUpload itself failed, the log line 'Failed to abort multipart upload' appears; clean up uncommitted multipart uploads via bucket lifecycle rules.
  3. Retry the Put once root causes are addressed.
  4. Configure Object Storage bucket lifecycle to expire Incomplete/Uncommitted Multipart Uploads to avoid leaks from aborted uploads.

Example fix

# before: aborted multipart uploads accumulate in the bucket after repeated 318
# after: add a lifecycle rule to auto-expire uncommitted multipart uploads
oci os object-lifecycle-policy put --bucket-name tf-state --file lifecycle.json
# lifecycle.json:
# {"items":[{"name":"expire-multipart","action":"ABORT","timeAmount":1,"timeUnit":"DAYS","isEnabled":true}]}
Defensive patterns

Strategy: retry

Type guard

func isMultipartAborted(err error) bool {
    return err != nil && strings.Contains(err.Error(), "multipart upload aborted")
}

Try / catch

// After an aborted multipart upload, confirm the abort succeeded before retrying
if isMultipartAborted(err) {
    // optionally list/abort any lingering uncommitted multipart uploads for the object
    log.Println("[WARN] multipart upload aborted; verify bucket lifecycle cleans uncommitted uploads")
}

Prevention

When it happens

Trigger: A worker that hit an error path which did not enqueue a response; a worker panic/recover gap; the errChan drain loop returned without error but responses are short due to channel ordering edge cases.

Common situations: Same root causes as 317 (per-part failures) but manifesting through the count-mismatch branch rather than the per-response check; concurrency edge cases in the worker channel protocol.

Related errors


AI-assisted analysis of hashicorp/terraform@d32a084675 (2026-08-11). Data as JSON: /api/errors/8cadcd8926e81a55. Report an issue: GitHub.

Appendix: source

Thrown at internal/backend/remote-state/oci/multipart_upload.go:147

		commitMultipartUploadPartDetails[i] = objectstorage.CommitMultipartUploadPartDetails{
			PartNum: common.Int(partNumber),
			Etag:    common.String(etag),
		}
		i++
	}

	if len(commitMultipartUploadPartDetails) != len(sourceBlocks) {
		abortReq := objectstorage.AbortMultipartUploadRequest{
			UploadId:      multipartUploadResponse.MultipartUpload.UploadId,
			NamespaceName: multipartUploadResponse.Namespace,
			BucketName:    multipartUploadResponse.Bucket,
			ObjectName:    multipartUploadResponse.Object,
		}
		_, abortErr := multipartUploadData.client.objectStorageClient.AbortMultipartUpload(context.Background(), abortReq)
		if abortErr != nil {
			logger.Error(fmt.Sprintf("Failed to abort multipart upload: %s", abortErr))
		}
		return fmt.Errorf("not all parts uploaded successfully, multipart upload aborted")
	}

	commitMultipartUploadRequest := objectstorage.CommitMultipartUploadRequest{
		UploadId:           multipartUploadResponse.MultipartUpload.UploadId,
		NamespaceName:      multipartUploadResponse.Namespace,
		BucketName:         multipartUploadResponse.Bucket,
		ObjectName:         multipartUploadResponse.Object,
		OpcClientRequestId: multipartUploadResponse.OpcClientRequestId,
		RequestMetadata:    multipartUploadRequest.RequestMetadata,
		CommitMultipartUploadDetails: objectstorage.CommitMultipartUploadDetails{
			PartsToCommit: commitMultipartUploadPartDetails,
		},
	}
	_, err = multipartUploadData.client.objectStorageClient.CommitMultipartUpload(context.Background(), commitMultipartUploadRequest)
	if err != nil {
		return fmt.Errorf("failed to commit multipart upload: %s", err)
	}

View on GitHub (pinned to d32a084675)