Short answer: the server (or a proxy in front of it) rejected the request body as too large
error: RPC failed; HTTP 413 curl 22 The requested URL returned error: 413
send-pack: unexpected disconnect while reading sideband packet
fatal: the remote end hung up unexpectedly
Everything up-to-date413 is the HTTP status "Content Too Large" (RFC 9110 §15.5.14). It comes from the remote server or a reverse proxy in front of it, not from your git client. The final Everything up-to-date means nothing was pushed — it is not a success. There are two fixes: (1) raise the upload limit on the server side, or (2) take the large file out of the push.
Scope:
git pushover HTTPS failing with 413. For auth errors see SSH Permission denied (publickey); for non-fast-forward rejections see git push rejected: non-fast-forward.
Cause
- A request-body limit on the proxy/web server. nginx's
client_max_body_sizedefaults to1mand returns 413 for larger requests (nginx docs). This is common with self-hosted GitLab or Gitea behind nginx. - A large file in the push. Build output, datasets or videos committed by mistake make the push request (the pack) exceed the limit.
http.postBufferis usually neither the cause nor the fix. The git docs say raising it "is not, in general, an effective solution for most push problems" and is meant for servers or proxies that don't support chunked transfer (git-config: http.postBuffer). In the test below, setting it to 50 MiB still returned 413.- Pushing to GitHub: GitHub blocks files larger than 100 MiB and warns above 50 MiB (GitHub Docs). You get GitHub's rejection message rather than 413, but the "remove the large file" steps below apply as-is.
Check commands
1) See who returns the 413. GIT_TRACE_CURL prints HTTP request and response headers (git docs).
GIT_TRACE_CURL=1 GIT_TRACE_CURL_NO_DATA=1 git push origin main 2>&1 \
| grep -E "Send header: POST|Recv header: HTTP/|Recv header: Server"=> Send header: POST /repo.git/git-receive-pack HTTP/1.1
<= Recv header: HTTP/1.1 413 Request Entity Too LargeThe 413 comes back on the git-receive-pack POST, and the Server: header (for example nginx) tells you which layer blocked it.
2) See what this push contains and which object is largest, using git cat-file --batch-check.
git log --oneline @{u}..HEAD
git rev-list --objects @{u}..HEAD \
| git cat-file --batch-check='%(objecttype) %(objectname) %(objectsize) %(rest)' \
| sort -k3 -n -r | head -5blob f893be8925fb500da6eff6f019f7a4e09d002b18 5000000 big.bin
commit 2b56827b2eee814c4e8070d5cfdce446f703e082 203The 5,000,000-byte big.bin is the culprit.
Fix steps
A. If you run the server: raise the limit
server {
# ...
location /repo.git/ {
client_max_body_size 50m; # value is an example; size it to your largest push
# ... existing proxy_pass / fastcgi settings
}
}sudo nginx -t && sudo nginx -s reloadclient_max_body_size is allowed in http, server and location contexts (nginx docs), so raise it only for the git path.
B. If the large file is only in your last, unpushed commit: drop it from the commit (the method GitHub Docs describe, source)
git rm --cached big.bin
echo "big.bin" >> .gitignore
git add .gitignore
git commit --amend -CHEAD
git push origin mainC. If the file must stay versioned: move it to Git LFS. git lfs migrate import rewrites the history of the given refs and replaces the files with LFS pointers (git-lfs-migrate). Exclude refs that are already pushed with --exclude-ref so shared history is not rewritten. The server must support LFS; GitHub's LFS per-file limits depend on your plan (GitHub Docs: Git LFS).
git lfs install --local
git lfs migrate import --include="*.dat" \
--include-ref=refs/heads/main --exclude-ref=refs/remotes/origin/main
cat .gitattributes # *.dat filter=lfs diff=lfs merge=lfs -text
git show HEAD:big2.dat | head -3 # version https://git-lfs.github.com/spec/v1 ...D. If the file is buried in an earlier commit: remove it from history with git filter-repo, which GitHub Docs also recommend (source, git-filter-repo docs). It rewrites history, so work in a fresh clone and tell collaborators first.
git clone <repo-url> repo-clean && cd repo-clean
git filter-repo --path old.iso --invert-paths
git remote add origin <repo-url> # filter-repo removes the origin remoteIf you pushed a secret, revoke it before cleaning history: Accidentally pushed .env / API keys to git.
Test environment and results
In a local sandbox (Debian, git 2.47.3, nginx 1.26.3 + git-http-backend, git-lfs 3.6.1, git-filter-repo), pushing a 5 MB file to an HTTPS remote with client_max_body_size 1m reproduced the exact error and trace output above. With -c http.postBuffer=52428800 the push still got 413. After step B the push succeeded. After step C the file became an LFS pointer. After step D the file was gone from history and the origin remote had been removed. For step A, a POST of the same size no longer got 413 after raising the limit to 50m.
Last checked: 2026-10-22. Behavior can differ between versions, so check the docs for your git and nginx versions.
Debian (box sandbox) · git 2.47.3 · nginx 1.26.3 + git-http-backend (fcgiwrap) · git-lfs 3.6.1 · git-filter-repo · Run on 2026-10-22
git push (client_max_body_size 1m, 5MB file) -> HTTP 413
git -c http.postBuffer=52428800 push -> still 413
GIT_TRACE_CURL=1 git push
git rev-list --objects @{u}..HEAD | git cat-file --batch-check
git rm --cached + git commit --amend -CHEAD + git push -> success
git lfs migrate import --include=*.dat --exclude-ref=refs/remotes/origin/main
git filter-repo --path old.iso --invert-paths
nginx client_max_body_size 50m -> POST no longer 413Error text reproduced; steps B/C/D verified; step A verified at the HTTP layer
Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us
This article has no recorded human check (date and scope) yet.
Comments
Be the first to comment.