git lfs pull seems to not respect 429 retry-after headers
Describe the bug This is a follow-up to https://github.com/git-lfs/git-lfs/issues/6007. After the fix was merged we saw immediate improvements. But we were later puzzled as the issue was still happening in CI (GitLab Runner).
We were finally able to reproduce it locally by following the checkout steps of gitlab-runner, which always does a git lfs pull after initially forcing GIT_LFS_SKIP_SMUDGE:
https://gitlab.com/gitlab-org/gitlab-runner/-/blob/main/shells/abstract.go#L666-671
This brought bursts of 429s again without proper waiting in the batches. Not sure how the code path can be different from the clone command but seems to be the case.
To Reproduce Steps to reproduce the behavior:
- Set a low rate limit server-side for LFS for an easier reproduction, e.g 10 requests per 30 minutes in this example
- Find a repo with lots of LFS files, clone with the smudge filter first then lfs pull:
GIT_LFS_SKIP_SMUDGE=1 git clone https://git.example.com/repo.git
cd repo
export GIT_CURL_VERBOSE=1
export GIT_TRANSFER_TRACE=1
git lfs pull 2>&1 | tee trace.txtExpected behavior 429 headers are respected and git-lfs waits during pulls/fetches.
System environment
Linux fedora 6.16.3-200.fc42.x86_64 #1 SMP PREEMPT_DYNAMIC Sat Aug 23 17:02:17 UTC 2025 x86_64 GNU/LinuxAlso seen in CI runners, but this repro was run locally.
Output of git lfs env
nejc@fedora:~$ git lfs env
git-lfs/3.7.0 (GitHub; linux amd64; go 1.24.4; git 92dddf56)
git version 2.51.0
LocalWorkingDir=
LocalGitDir=
LocalGitStorageDir=
LocalMediaDir=lfs/objects
LocalReferenceDirs=
TempDir=lfs/tmp
ConcurrentTransfers=8
TusTransfers=false
BasicTransfersOnly=false
SkipDownloadErrors=false
FetchRecentAlways=false
FetchRecentRefsDays=7
FetchRecentCommitsDays=0
FetchRecentRefsIncludeRemotes=true
PruneOffsetDays=3
PruneVerifyRemoteAlways=false
PruneVerifyUnreachableAlways=false
PruneRemoteName=origin
LfsStorageDir=lfs
AccessDownload=none
AccessUpload=none
DownloadTransfers=basic,lfs-standalone-file,ssh
UploadTransfers=basic,lfs-standalone-file,ssh
GIT_EXEC_PATH=/usr/libexec/git-core
git config filter.lfs.process = "git-lfs filter-process"
git config filter.lfs.smudge = "git-lfs smudge -- %f"
git config filter.lfs.clean = "git-lfs clean -- %f"Additional context
trace.txt: with lfs pull trace-clone.txt: with normal clone (sorry this is truncated and interrupted, it was taking much longer as it waited properly, but I can add provide a smaller one if needed)
For a bit of extra context here's some log aggregates from ELK matching activity from the two client-side traces, the first one with lfs pull and the second the normal clone, showing the burst of 429 responses vs. only a few over a longer period with proper retries:
Source: git-lfs/git-lfs