error: RPC failed; curl 56 / HTTP 400 on git push (tested)

error: RPC failed; curl 56 ... and error: RPC failed; HTTP 400 both show up on git push over HTTP(S) when a commit is large. Both come from the same place: git's HTTP client switches from one buffered request to a streamed (chunked) one once the push exceeds http.postBuffer, and plenty of real servers and proxies choke on that. We set up a real smart-HTTP git server and pushed large commits at different postBuffer sizes to show it happening.

1. What the error means

RPC failed means the HTTP request that carries your push data (the "git-receive-pack RPC") did not complete normally. curl error 56 is CURLE_RECV_ERROR, "failure receiving network data" — the connection dropped mid-read. A following HTTP 400 or 413 means a server or proxy in the middle rejected the request outright. Per git's docs and source, the common trigger for both is the same: a large push forces git to stream the request body instead of sending it as one buffered chunk, and something between client and server does not handle that well.

2. Our test setup

We built a real (not simulated) git smart-HTTP server: a small Python CGI wrapper that runs the system's git-http-backend for each request, backed by a bare repo, listening on 127.0.0.1:8990. We cloned it, committed a single large binary file (29 MB, then 40 MB), and pushed with git push at different http.postBuffer settings, capturing the exact client output and server log each time.

$ git --version
git version 2.47.3
$ git config --get http.postBuffer
(empty — unset)

Per the git docs, an unset http.postBuffer defaults to 1 MiB (1,048,576 bytes). Below that size, git buffers the whole request and sends a normal Content-Length POST. Above it, git switches to Transfer-Encoding: chunked so it never has to hold the full pack in memory.

3. Reproducing the failure

With the default (unset, 1 MiB) postBuffer and a 40 MB commit, the push failed every time:

$ git push origin master
send-pack: unexpected disconnect while reading sideband packet
fatal: the remote end hung up unexpectedly

The server log showed the POST carrying the pack came back, then the connection was torn down before git's receive-pack report-status could be read. We also saw this with http.postBuffer explicitly set to 100 or 200 bytes against a 29 MB commit — same client error, same point of failure: as soon as the request stops fitting in the buffer and git starts chunked streaming, our server (a minimal CGI wrapper, representative of many hand-rolled or older git-http-backend setups) cannot keep up and the connection drops.

This is the same family as error: RPC failed; curl 56 ... Recv failure: Connection reset by peer and error: RPC failed; HTTP 400 reported against real servers: curl 56 is what the client reports when the drop happens while still receiving the response; HTTP 400/413 is what it reports when a proxy or load balancer in front of the git server rejects the oversized or chunked request outright. Per git's own issue tracker and widely-reported cases against GitLab/Apache/nginx-fronted git servers, both are triggered by the same chunked-vs-buffered boundary we reproduced here — we are labelling the exact wording "curl 56" / "HTTP 400" as per those reports, not measured verbatim on our minimal test server, because our server's own error path produced the disconnect above instead of forwarding a clean 400.

4. The fix: raise http.postBuffer

Raising http.postBuffer above the size of your largest push makes git send it as one buffered request again, avoiding the chunked path that trips up the server. We set it to 50 MiB and re-ran the same 29 MB push:

$ git config http.postBuffer 52428800
$ git push origin master
To http://127.0.0.1:8990/remote.git
 * [new branch]      master -> master

Exit code 0, and the commit was confirmed present in the remote bare repo afterward (git show-ref listed it). The fix is global per-repo (or use --global for every repo):

# this repo only
git config http.postBuffer 524288000

# every repo for this user
git config --global http.postBuffer 524288000

524288000 is 500 MiB; size it to comfortably exceed your largest expected push. There is no real downside to a large value for normal use — it only changes how big a request can be before git switches to streaming, not memory used for small pushes.

5. If raising postBuffer does not fix it

If the server side is timing out rather than rejecting the size, see 504 Gateway Timeout. If the issue is the server refusing to resolve or connect at all, see git could not resolve host.

Frequently asked questions

What does curl error 56 mean in "RPC failed; curl 56"?

It is CURLE_RECV_ERROR: curl was reading the HTTP response and the connection failed or was reset before it finished. On a git push this usually happens right as git switches to streaming (chunked) upload for a large pack, and the server or a proxy in between drops the connection partway through.

What is http.postBuffer and what is its default?

It is the maximum number of bytes git will buffer before switching an HTTP POST to chunked Transfer-Encoding. Per git's docs, if unset it defaults to 1 MiB (1,048,576 bytes). We confirmed on git 2.47.3 that the config key is empty/unset by default.

Does raising http.postBuffer always fix RPC failed?

It fixes the cases caused by the buffered-vs-chunked switch, which is what we reproduced. It does not fix a hard size cap set by a proxy or load balancer in front of the git server (that shows as 413, not something postBuffer controls) or failures caused by an unstable network connection.

Is there a downside to setting http.postBuffer very high?

No meaningful one for normal use. It only raises the threshold before git streams instead of buffers; it does not pre-allocate that much memory for small pushes. Setting it to e.g. 500 MiB globally is a common, safe default.

Why does the same push work over SSH but fail over HTTPS?

SSH's transport does not have a buffered-vs-chunked-HTTP boundary at all, so there is nothing for a postBuffer-style limit to trip. If HTTPS pushes keep failing on large commits and you cannot change server-side limits, switching the remote URL to SSH sidesteps the problem entirely.

Written with AI assistance. Measured on 2026-10-02 with git 2.47.3 (client and server, same binary), against a real smart-HTTP git server: a Python 3.13 CGI wrapper around the system's /usr/lib/git-core/git-http-backend, serving a bare repo over plain HTTP on 127.0.0.1. Pushes of 29-40 MB single-file commits were run with different http.postBuffer values. The literal strings "RPC failed; curl 56" and "HTTP 400" were not produced by our minimal test server (see note in section 3); they are documented from git's source and widely-reported issue threads, labelled accordingly below. PlainHeaders is our extension; curl, git and Python are free.