Interacting with Git: Cryptic RPC Errors, HTTPS, and SSH

PC_Load_Letter_590

In my experience, working with a Git repository hosted by Gitlab, Github, or Gitorious has generally been issue free and enjoyable. Recently, however, three members of my team ran across the same cryptic RPC error when trying to push changes to a remote repository on Gitlab:

error: RPC failed; result=22, HTTP code = 411

In two cases, developers were trying to push new framework libraries (they were moderately sized, 2-9 MB). In the third case, a designer was trying to push a large batch of image assets. In all cases, the problem was caused by using the HTTPS protocol with a server configuration that disallowed individual files larger than 1 MB.

After some basic investigation (thanks Stack Overflow!), we found that using the SSH protocol with Git solved the problem. This type of issue could trip up a new user of Git, so I am going to use this post to briefly describe the problem and summarize the pros/cons of using HTTPS vs. SSH protocols to talk to remote repositories.

RPC failed… what?!

The first problem a non-expert Git user has is trying to understand what this error even means. To me, it reads like something out of the movie “Office Space”, when the main character Michael Bolton yells in frustration: PC Load Letter?! What the **** does that even mean!?!

We can break the error down:

  • RPC a “remote procedure call” has failed. As an example, Github uses BERT-RPC to expose Git repositories as a service. Here’s a detailed post explaining BERT-RPC. I wasn’t able to find what Gitlab is using, and I’d be interested to hear from anyone who might know.
  • http 411 is a “Length Required” error. The specification tells us that the server expected a “Content-Length” specification. This gives us some clue that the Git error has to do with file size but isn’t specific enough to be very helpful.

Since this is fundamentally an HTTPS configuration error, switching to SSH protocol to interact with Gitlab will solve it. I’ll compare SSH to https later in this post, but for now, let’s look at two solutions that might make https work.

Possible Solutions for HTTPS

The most-up-voted answer on Stack Overflow for this problem is to change your local Git configuration to allow very large files. For example, this will up the per-file limit to 500 MB:

git config http.postBuffer *bytes*
git config http.postBuffer 524288000

I tried this approach, but it didn’t work. In my case, the problem was with the server (nginx) configuration that hosts the Git repository. Here’s a fix that did work, which may not be appropriate for everyone:

http {
    # ...
    client_max_body_size 16M;
    # ...

Even at a company like Atomic Object, with awesome problem solvers who will generally bend over backwards for a client or developer who needs help, it may not be worth the trouble of updating the server configuration. Enter the real solution: just use SSH!

Using SSH to Interact with Remote Repositories!

Git has a nice article describing Git server protocols. In short: while HTTPS is the easiest for a client to use (just plug in the URL in your Git clone command), SSH has several advantages:

  • Supports authenticated write access on your network
  • More efficient than HTTPS (faster!)
  • Relatively easy to set up (but not easier than HTTPS)
  • File size limit governed by Git (on Github, it’s 100 MB), not the server hosting the repository

The downside of SSH (relative to HTTPS) is that it doesn’t support anonymous writes. The user needs to be authenticated (this is, of course, also an positive thing). So it requires the client do a little bit more work to set up.

If you have never created a SSH key, here is how it’s done:

1. Generate the key with your email address.

Then enter your desired password with the following command:

ssh-keygen -t rsa -C "[email protected]"

2. Copy your public SSH key.

You’ll need to add it to your profile on Github, Gitlab or Gitorious.

cat ~/.ssh/id_rsa.pub

3. Add the public SSH key into your Github, GitLab, or Gitorious profile.

When using Github, go to Settings, then “SSH Keys” and click “Add SSH Key”. A box will open where you can paste in your public key, which should look something like this:

ssh-rsa AAAAbbHvMnZL+nEAAAADAQABAAABAQDPB1h1dYHgI8WIVhEQ5Cn7PKt1PXm6yqsohpjZ8pZBj1tTFTfq8z8
+YljrDsqSSc7oa67kIfNbAmd/yC6stjI+IDtHd5f2O+3q7+YvPeYzvVF5byEQPLDX+PW2bnHWJgJJKyjdYckHGLLW1w
HQILiwyYl+hFuEkkOs5VVBjwbyEL6vzXvzTYX06IP4j5FoWtAvf32lkaNbaPLZHiBhwGxCopIsvNd9Pn4qm80wH3bC4
Qg/GQnMMKNjsl8726C880/xcnjKvfg1t8Z/Hfme69UM17L4BWACxHcWZgDUBMbL1Yo7fPrgLW/plg+Tz2UpNBDUTjWs
wfaoLjzsju0jbw+B [email protected]

It is very important to note that this is the public, not private key. You can tell because the private SSH key will start with the following line -----BEGIN RSA PRIVATE KEY-----.

4. Finally, switch to SSH in your local Git repository.

For example, using Github:

git remote set-url origin [email protected]:jnfisher/ios-curve-interpolation.git

If you are having problems using SSH, more details can be found in this Github article.