What's Going On
You're cloning or pushing a repo, everything looks fine for a few seconds, then Git dies halfway through:
error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: the remote end hung up unexpectedly
The culprit is almost always repo size. Git's default HTTP buffer is just 1 MB. When a repo is large โ say, 500 MB with years of history and binary assets โ the server starts pumping data, the buffer fills up, the connection stalls, and the remote drops it.
Not a permissions issue. Not a firewall. A buffer/timeout mismatch between Git's HTTP layer and the remote server.
Debug: Confirm the Root Cause
Before touching any settings, verify what you're actually dealing with.
# Check current http.postBuffer setting (default is 1 MB = 1048576)
git config --global http.postBuffer
# No output means it's still at the 1 MB default
Then run the clone with full verbose logging to pinpoint exactly where it breaks:
GIT_CURL_VERBOSE=1 GIT_TRACE=1 git clone https://github.com/your/repo.git 2>&1 | tail -50
Scan for RPC failed, curl: (18), or transfer closed. Those three strings confirm it's a buffer issue โ and the fix below will solve it.
Solution 1: Increase the HTTP Post Buffer (Fix for Most Cases)
Start here. This single setting resolves roughly 90% of curl 18 failures.
# 500 MB โ handles most large repos
git config --global http.postBuffer 524288000
# 1 GB โ for repos over 1 GB or very long histories
git config --global http.postBuffer 1073741824
Retry the clone or push:
git clone https://github.com/your/repo.git
# or
git push origin main
Verification: No RPC error means it worked. Run git log --oneline -5 inside the cloned directory to confirm the history arrived intact.
Solution 2: Clone Shallow First, Then Fetch Full History
Some repos have 10,000+ commits. Even a 500 MB buffer isn't always enough for those. Clone with just the latest snapshot, then pull the rest in smaller bites.
# Download only the most recent commit โ fast and tiny
git clone --depth 1 https://github.com/your/repo.git
cd repo
# Fetch the full history in incremental chunks
git fetch --unshallow
The --depth 1 clone transfers maybe a few MB instead of the full history. Once you're inside with a stable connection, --unshallow fetches the rest gradually rather than in one massive burst that overwhelms the buffer.
Verification: After --unshallow finishes:
git log --oneline | wc -l
# Shows the full commit count โ not 1
Solution 3: Switch to SSH Instead of HTTPS
The curl 18 error only happens over HTTP. SSH uses a completely different transport โ no HTTP buffer, no RPC layer, no curl.
# Switch the remote URL from HTTPS to SSH
git remote set-url origin git@github.com:your-username/repo.git
# Confirm the change
git remote -v
# Retry
git push origin main
# or clone fresh:
git clone git@github.com:your-username/repo.git
SSH handles multi-gigabyte transfers without breaking a sweat. It's the most reliable long-term fix if you have SSH access. Corporate networks that block port 22 can sometimes tunnel SSH over port 443 โ check your Git host's docs for the ssh.github.com config.
Solution 4: Disable the Timeout and Lower Compression
Slow connections (think hotel WiFi, mobile hotspot, or a VPN bottleneck) trigger a different version of this error: the server cuts the connection after a timeout, not because the buffer filled. Two config changes help:
# Effectively disable Git's low-speed timeout
git config --global http.lowSpeedLimit 0
git config --global http.lowSpeedTime 999999
# Skip zlib compression โ larger transfers but less CPU overhead
git config --global core.compression 0
lowSpeedLimit 0 tells Git not to abort based on transfer speed. core.compression 0 trades file size for speed โ each object transfers a bit larger but doesn't need CPU time to compress first. On a slow connection where CPU isn't the bottleneck, this is almost always a net win.
Stack these settings on top of Solution 1's buffer increase for the best results on a sluggish network.
Solution 5: Push Commits in Smaller Batches
Clone works fine but git push keeps dying? You probably have a large backlog of commits โ common after working offline for a week or more. Push them in chunks instead of all at once.
# See what's waiting to be pushed
git log origin/main..HEAD --oneline
# Push the first ~100 commits
git push origin <hash-of-100th-commit>:main
# Push the rest normally
git push origin main
Grab the actual hash from git log output. If you have 400 unpushed commits, push them 100 at a time โ four smaller operations instead of one giant one that times out.
Checking Your Config After Fixes
See everything you've changed at once:
git config --global --list | grep -E 'http|core.compression'
With all fixes applied, you should see:
http.postbuffer=524288000
http.lowspeedlimit=0
http.lowspeedtime=999999
core.compression=0
Which Fix to Try First
- Default starting point: Increase
http.postBuffer(Solution 1) โ fixes 9 out of 10 cases. - Still failing: Add
--depth 1then--unshallow(Solution 2). - Have SSH access: Switch to SSH (Solution 3) โ most reliable permanently.
- Slow or unstable connection: Pair Solution 4's timeout settings with the buffer increase.
- Push-only problem: Push in batches (Solution 5).
Lessons Learned
Git's 1 MB default buffer dates from an era when most repos were small. Today's monorepos can hit 2โ5 GB. A project with ten years of history, a hundred contributors, and some committed binaries will easily transfer 300โ500 MB in a single clone operation โ 300ร what the default buffer can handle.
Setting up a new dev environment? Add the buffer setting to your global config before you start cloning anything large. It takes five seconds and avoids this headache entirely.
Teams running very large repositories should also look at Git LFS to move binaries out of the main object store, and schedule periodic git gc --aggressive runs to pack loose objects. A well-maintained repo with LFS can cut clone size by 80% or more โ far less data to transfer means far fewer timeout problems.

