hashicorp/terraform · error

failed to commit multipart upload: %s

Error message

failed to commit multipart upload: %s

What it means

Raised in multiPartUploadImpl when the final CommitMultipartUpload API call fails. All parts uploaded, but the commit that assembles them into the final object was rejected by OCI. The wrap surfaces the raw SDK error (parts list mismatch, auth, throttling, the upload session expired, or a service fault).

Source

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

			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)
	}

	return nil
}
func (m MultipartUploadData) objectMultiPartSplit() ([]objectStorageSourceBlock, error) {
	dataSize := int64(len(m.Data))
	offsets, partSize, err := SplitSizeToOffsetsAndLimits(dataSize)
	if err != nil {
		return nil, fmt.Errorf("error splitting data into parts: %s", err)
	}
	sourceBlocks := make([]objectStorageSourceBlock, len(offsets))
	for i := range offsets {
		start := offsets[i]
		end := start + partSize
		if end > dataSize {
			end = dataSize
		}
		sourceBlocks[i] = objectStorageSourceBlock{

View on GitHub (pinned to c9def3e214)

Solutions

  1. Read the wrapped ErrorCode: 404/expired -> the multipart session is gone, re-run the whole upload; InvalidParameter -> a part etag/part-number is stale.
  2. Re-run the apply; commit failures are usually transient or resolved by a fresh upload session.
  3. Ensure the upload completes within OCI's multipart-upload retention window (avoid long stalls between parts).
  4. For throttling, reduce parallel writers and rely on retry policy; sustained issues need a service-limit increase.
Defensive patterns

Strategy: retry

Validate before calling

// Pre-flight: ensure the upload session will commit promptly (no long stalls):
// keep total upload time under OCI's multipart-upload retention window.

Type guard

var se common.ServiceError
if errors.As(err, &se) {
    switch se.GetHTTPStatusCode() {
    case 404: // upload-id expired/aborted -> full re-run
    case 400: // stale etag/part list
    case 429: // throttled
    }
}

Try / catch

_, err = c.objectStorageClient.CommitMultipartUpload(ctx, commitReq)
if err != nil {
    return fmt.Errorf("failed to commit multipart upload: %s", err)
}

Prevention

When it happens

Trigger: objectStorageClient.CommitMultipartUpload (multipart_upload.go:161) returns a non-nil error: 400/InvalidParameter when PartsToCommit etag/part numbers do not match what the service recorded, 404 when the upload-id expired or was aborted elsewhere, 401/403, 429, or 5xx/network.

Common situations: Upload session took too long and OCI reaped the multipart upload; a part was retried server-side changing its etag so the commit list is stale; IAM permission revoked mid-run; throttling at commit; transient service fault.

Related errors


AI-assisted analysis of hashicorp/terraform@c9def3e214 (2026-08-07). Data as JSON: /api/errors/00e42de86a5ef8a3. Report an issue: GitHub.