Skip to Content [alt-c]

September 24, 2026

macOS Can't Clone "Dumb" Git Repositories Over HTTP/2

Try the following Git clone with libcurl 8.7.1 (which happens to be the version shipped in macOS 14.6 and newer) and it fails or hangs:

git clone https://software.sslmate.com/src/macosgitbug.git

Disable HTTP/2 and it works:

git clone -c http.version=HTTP/1.1 https://software.sslmate.com/src/macosgitbug.git

The bug is in libcurl 8.7.1's handling of the FAILONERROR option. FAILONERROR tells libcurl to treat unsuccessful HTTP status codes, such as 404, as a request failure. When HTTP/2 is used, the bug causes other in-flight requests on the same HTTP/2 connection to also fail, or even to hang. The bug was fixed over two years ago in curl 8.8.0, but Apple continues to ship a buggy version, even in last week's macOS 27 release.

When retrieving a repository over the "dumb" transfer protocol, Git makes certain HTTP requests with the FAILONERROR option set, notably requests to objects/info/alternates and objects/info/http-alternates, which list alternate locations where the repository's content can be found. Most repositories don't have alternate locations, so these files don't exist, and the URLs return 404 errors. When the buggy version of libcurl is used, this 404 error causes Git's other HTTP requests to also fail, and Git is unable to clone the repository.

The bug affects not just direct uses of Git, but also go get with GOPROXY=direct or a module listed in GOPRIVATE, which invoke Git under the hood.

Working around the bug on the client side is easy: just force Git to use HTTP/1.1:

git config --global http.version HTTP/1.1

Even better, install Git through MacPorts, since Apple has clearly dropped the ball. (Homebrew won't help - unlike MacPorts, they use the system libcurl.)

But most clients won't know to apply this workaround, and if you host Git repositories with the dumb protocol, you probably want macOS users to be able to clone your repositories! Fortunately, there's a really easy server-side workaround: create objects/info/alternates and objects/info/http-alternates as empty files, so they don't return a 404 error anymore. Git treats the empty files the same as it would treat a 404 error, and the libcurl bug isn't triggered.

touch /path/to/repo.git/objects/info/alternates /path/to/repo.git/objects/info/http-alternates

The bug isn't triggered when the repository supports the "smart" protocol, which is why macOS can clone repositories from GitHub and other popular forges despite them using HTTP/2. But I do not want to use the smart protocol for my repositories: although it has many advantages over the dumb protocol, it requires heavy server-side computation and even a modest load can knock a server over. In contrast, the dumb protocol can be served entirely from static files, which makes a huge difference for withstanding the horde of AI scrapers currently terrorizing the Web. I hope that we will see innovations to the dumb protocol that bring it some of the advantages of the smart protocol while still being served from static files.

Thanks to Romain of the Traefik project for noticing that SSLMate's repos couldn't be cloned on macOS, Sebastiaan van Stijn for asking that this problem be reported upstream instead of silently hacked around in Traefik's go.mod file, and Kangmin Kim for pointing me to the libcurl bug as the root cause. Claude Code proposed the empty file workaround so I didn't have to waste (too much) time on this. Zero thanks to Apple for shipping a two-year-old show-stopping bug in libcurl.

Comments

No comments yet.

Post a Comment

Your comment will be public. To contact me privately, email me. Please keep your comment polite, on-topic, and comprehensible. Your comment may be held for moderation before being published.

(Optional; will be published)

(Optional; will not be published)

(Optional; will be published)

  • Blank lines separate paragraphs.
  • Lines starting with > are indented as block quotes.
  • Lines starting with two spaces are reproduced verbatim (good for code).
  • Text surrounded by *asterisks* is italicized.
  • Text surrounded by `back ticks` is monospaced.
  • URLs are turned into links.
  • Use the Preview button to check your formatting.