Sửa lỗi Git Clone/Push thất bại: error: RPC failed; curl 18 transfer closed with outstanding read data remaining

intermediate📦 Git2026-05-03| Git 2.x trên Linux, macOS, Windows — thường xảy ra với repository lớn qua HTTP/HTTPS

Error Message

error: RPC failed; curl 18 transfer closed with outstanding read data remaining fatal: the remote end hung up unexpectedly
#git#clone#push#rpc#large-repo#http-buffer

Chuyện Gì Đang Xảy Ra

Bạn đang clone hoặc push một repo, mọi thứ có vẻ ổn trong vài giây, rồi Git đột ngột chết giữa chừng:

error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: the remote end hung up unexpectedly

Nguyên nhân gần như luôn là kích thước repo. Buffer HTTP mặc định của Git chỉ có 1 MB. Khi repo lớn — chẳng hạn 500 MB với nhiều năm lịch sử commit và file nhị phân — server bắt đầu đẩy dữ liệu, buffer đầy, kết nối bị đình trệ, và phía remote ngắt kết nối.

Đây không phải vấn đề quyền truy cập. Không phải firewall. Mà là sự không khớp giữa buffer/timeout của lớp HTTP trong Git và server từ xa.

Debug: Xác Nhận Nguyên Nhân Gốc Rễ

Trước khi chỉnh bất kỳ cài đặt nào, hãy xác minh bạn đang thực sự đối mặt với vấn đề gì.

# Kiểm tra cài đặt http.postBuffer hiện tại (mặc định là 1 MB = 1048576)
git config --global http.postBuffer

# Không có output nghĩa là vẫn đang dùng giá trị mặc định 1 MB

Sau đó chạy lệnh clone với log verbose đầy đủ để xác định chính xác nơi lỗi xảy ra:

GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://github.com/your/repo.git 2>&1 | tail -50

Tìm kiếm các chuỗi RPC failed, curl: (18), hoặc transfer closed. Ba chuỗi này xác nhận đây là vấn đề buffer — và cách fix dưới đây sẽ giải quyết được.

Giải Pháp 1: Tăng HTTP Post Buffer (Xử Lý Được Hầu Hết Trường Hợp)

Bắt đầu từ đây. Một cài đặt duy nhất này giải quyết khoảng 90% các lỗi curl 18.

# 500 MB — xử lý được hầu hết các repo lớn
git config --global http.postBuffer 524288000

# 1 GB — dành cho repo trên 1 GB hoặc lịch sử rất dài
git config --global http.postBuffer 1073741824

Thử lại lệnh clone hoặc push:

git clone https://github.com/your/repo.git
# hoặc
git push origin main

Kiểm tra: Không còn lỗi RPC nghĩa là đã thành công. Chạy git log --oneline -5 bên trong thư mục vừa clone để xác nhận lịch sử đã được tải về đầy đủ.

Giải Pháp 2: Clone Shallow Trước, Rồi Fetch Toàn Bộ Lịch Sử

Một số repo có hơn 10.000 commit. Ngay cả buffer 500 MB đôi khi vẫn không đủ. Hãy clone chỉ với snapshot mới nhất, rồi kéo phần còn lại theo từng phần nhỏ hơn.

# Chỉ tải về commit gần nhất — nhanh và nhẹ
git clone --depth 1 https://github.com/your/repo.git

cd repo

# Fetch toàn bộ lịch sử theo từng phần tăng dần
git fetch --unshallow

Lệnh clone với --depth 1 chỉ truyền vài MB thay vì toàn bộ lịch sử. Khi đã vào trong repo với kết nối ổn định, --unshallow sẽ fetch phần còn lại dần dần thay vì một lần ồ ạt làm tràn buffer.

Kiểm tra: Sau khi --unshallow hoàn tất:

git log --oneline | wc -l
# Hiển thị tổng số commit — không phải 1

Giải Pháp 3: Chuyển Sang SSH Thay Vì HTTPS

Lỗi curl 18 chỉ xảy ra qua HTTP. SSH dùng một giao thức truyền tải hoàn toàn khác — không có HTTP buffer, không có lớp RPC, không có curl.

# Đổi URL remote từ HTTPS sang SSH
git remote set-url origin git@github.com:your-username/repo.git

# Xác nhận thay đổi
git remote -v

# Thử lại
git push origin main
# hoặc clone mới:
git clone git@github.com:your-username/repo.git

SSH xử lý các file truyền nhiều gigabyte mà không gặp vấn đề gì. Đây là giải pháp lâu dài đáng tin cậy nhất nếu bạn có quyền truy cập SSH. Mạng công ty chặn cổng 22 đôi khi có thể tunnel SSH qua cổng 443 — kiểm tra tài liệu của Git host về cấu hình ssh.github.com.

Giải Pháp 4: Tắt Timeout Và Giảm Compression

Kết nối chậm (như WiFi khách sạn, điểm phát sóng di động, hoặc VPN bị bottleneck) gây ra một biến thể khác của lỗi này: server ngắt kết nối sau timeout, không phải vì buffer đầy. Hai thay đổi cấu hình sau có thể giúp ích:

# Về cơ bản tắt timeout tốc độ thấp của Git
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999

# Bỏ qua nén zlib — truyền tải lớn hơn nhưng tốn ít CPU hơn
git config --global core.compression 0

lowSpeedLimit 0 báo cho Git không hủy dựa trên tốc độ truyền tải. core.compression 0 đánh đổi kích thước file lấy tốc độ — mỗi object truyền lớn hơn một chút nhưng không cần thời gian CPU để nén trước. Trên kết nối chậm mà CPU không phải điểm nghẽn, đây hầu như luôn là lựa chọn có lợi hơn.

Kết hợp các cài đặt này với việc tăng buffer ở Giải Pháp 1 để đạt kết quả tốt nhất trên mạng chậm.

Giải Pháp 5: Push Commit Theo Từng Đợt Nhỏ

Clone hoạt động tốt nhưng git push liên tục chết? Bạn có thể có một lượng lớn commit tồn đọng — thường xảy ra sau khi làm việc offline cả tuần hoặc hơn. Hãy push theo từng phần thay vì tất cả cùng một lúc.

# Xem những gì đang chờ được push
git log origin/main..HEAD --oneline

# Push khoảng 100 commit đầu tiên
git push origin <hash-of-100th-commit>:main

# Push phần còn lại bình thường
git push origin main

Lấy hash thực tế từ output của git log. Nếu bạn có 400 commit chưa push, hãy push 100 commit mỗi lần — bốn thao tác nhỏ thay vì một thao tác khổng lồ bị timeout.

Kiểm Tra Cấu Hình Sau Khi Sửa

Xem tất cả những gì bạn đã thay đổi cùng một lúc:

git config --global --list | grep -E 'http|core.compression'

Với tất cả các bản sửa đã áp dụng, bạn sẽ thấy:

http.postbuffer=524288000
http.lowspeedlimit=0
http.lowspeedtime=999999
core.compression=0

Nên Thử Giải Pháp Nào Trước

  • Điểm khởi đầu mặc định: Tăng http.postBuffer (Giải Pháp 1) — xử lý được 9 trong 10 trường hợp.
  • Vẫn còn lỗi: Thêm --depth 1 rồi --unshallow (Giải Pháp 2).
  • Có quyền truy cập SSH: Chuyển sang SSH (Giải Pháp 3) — đáng tin cậy nhất về lâu dài.
  • Kết nối chậm hoặc không ổn định: Kết hợp cài đặt timeout của Giải Pháp 4 với việc tăng buffer.
  • Chỉ gặp vấn đề khi push: Push theo từng đợt (Giải Pháp 5).

Bài Học Rút Ra

Buffer mặc định 1 MB của Git có từ thời mà hầu hết các repo đều nhỏ. Ngày nay, các monorepo có thể lên tới 2–5 GB. Một dự án với mười năm lịch sử, hàng trăm contributor, và một số file nhị phân đã commit dễ dàng truyền tải 300–500 MB trong một lần clone — gấp 300 lần so với những gì buffer mặc định có thể xử lý.

Đang thiết lập môi trường dev mới? Hãy thêm cài đặt buffer vào config toàn cục trước khi bắt đầu clone bất cứ thứ gì lớn. Chỉ mất năm giây và tránh được hoàn toàn cơn đau đầu này.

Các team đang làm việc với repo rất lớn cũng nên xem xét Git LFS để chuyển file nhị phân ra khỏi object store chính, và lên lịch chạy git gc --aggressive định kỳ để đóng gói các object rời. Một repo được bảo trì tốt với LFS có thể giảm kích thước clone tới 80% hoặc hơn — ít dữ liệu cần truyền hơn đồng nghĩa với ít vấn đề timeout hơn nhiều.

Related Error Notes